2009-12-11 19:24:15 +10:00
/*
* Copyright 2009 Ben Skeggs
* Copyright 2008 Stuart Bennett
*
* Permission is hereby granted , free of charge , to any person obtaining a
* copy of this software and associated documentation files ( the " Software " ) ,
* to deal in the Software without restriction , including without limitation
* the rights to use , copy , modify , merge , publish , distribute , sublicense ,
* and / or sell copies of the Software , and to permit persons to whom the
* Software is furnished to do so , subject to the following conditions :
*
* The above copyright notice and this permission notice ( including the next
* paragraph ) shall be included in all copies or substantial portions of the
* Software .
*
* THE SOFTWARE IS PROVIDED " AS IS " , WITHOUT WARRANTY OF ANY KIND , EXPRESS OR
* IMPLIED , INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY ,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT . IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM , DAMAGES OR OTHER
* LIABILITY , WHETHER IN AN ACTION OF CONTRACT , TORT OR OTHERWISE , ARISING
* FROM , OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE .
*/
2020-06-22 11:08:51 +10:00
# define NVIF_DEBUG_PRINT_DISABLE
2016-05-20 09:22:55 +10:00
# include "nouveau_drv.h"
2009-12-11 19:24:15 +10:00
# include "nouveau_dma.h"
# include "nouveau_fbcon.h"
2020-06-22 11:08:51 +10:00
# include <nvif/push006c.h>
2010-10-05 16:41:29 +10:00
int
2009-12-11 19:24:15 +10:00
nv04_fbcon_copyarea ( struct fb_info * info , const struct fb_copyarea * region )
{
2010-03-30 05:34:14 +00:00
struct nouveau_fbdev * nfbdev = info - > par ;
2016-11-04 17:20:35 +10:00
struct nouveau_drm * drm = nouveau_drm ( nfbdev - > helper . dev ) ;
2012-07-20 08:17:34 +10:00
struct nouveau_channel * chan = drm - > channel ;
2020-06-22 11:31:45 +10:00
struct nvif_push * push = chan - > chan . push ;
2010-10-05 16:41:29 +10:00
int ret ;
2009-12-11 19:24:15 +10:00
2020-06-22 11:31:45 +10:00
ret = PUSH_WAIT ( push , 4 ) ;
2010-10-05 16:41:29 +10:00
if ( ret )
return ret ;
2009-12-11 19:24:15 +10:00
2020-06-22 11:31:45 +10:00
PUSH_NVSQ ( push , NV05F , 0x0300 , ( region - > sy < < 16 ) | region - > sx ,
0x0304 , ( region - > dy < < 16 ) | region - > dx ,
0x0308 , ( region - > height < < 16 ) | region - > width ) ;
PUSH_KICK ( push ) ;
2010-10-05 16:41:29 +10:00
return 0 ;
2009-12-11 19:24:15 +10:00
}
2010-10-05 16:41:29 +10:00
int
2009-12-11 19:24:15 +10:00
nv04_fbcon_fillrect ( struct fb_info * info , const struct fb_fillrect * rect )
{
2010-03-30 05:34:14 +00:00
struct nouveau_fbdev * nfbdev = info - > par ;
2016-11-04 17:20:35 +10:00
struct nouveau_drm * drm = nouveau_drm ( nfbdev - > helper . dev ) ;
2012-07-20 08:17:34 +10:00
struct nouveau_channel * chan = drm - > channel ;
2020-06-22 11:31:56 +10:00
struct nvif_push * push = chan - > chan . push ;
2010-10-05 16:41:29 +10:00
int ret ;
2009-12-11 19:24:15 +10:00
2020-06-22 11:31:56 +10:00
ret = PUSH_WAIT ( push , 7 ) ;
2010-10-05 16:41:29 +10:00
if ( ret )
return ret ;
2009-12-11 19:24:15 +10:00
2020-06-22 11:31:56 +10:00
PUSH_NVSQ ( push , NV04A , 0x02fc , ( rect - > rop ! = ROP_COPY ) ? 1 : 3 ) ;
2010-01-04 09:10:55 +10:00
if ( info - > fix . visual = = FB_VISUAL_TRUECOLOR | |
info - > fix . visual = = FB_VISUAL_DIRECTCOLOR )
2020-06-22 11:31:56 +10:00
PUSH_NVSQ ( push , NV04A , 0x03fc , ( ( uint32_t * ) info - > pseudo_palette ) [ rect - > color ] ) ;
2010-01-04 09:10:55 +10:00
else
2020-06-22 11:31:56 +10:00
PUSH_NVSQ ( push , NV04A , 0x03fc , rect - > color ) ;
PUSH_NVSQ ( push , NV04A , 0x0400 , ( rect - > dx < < 16 ) | rect - > dy ,
0x0404 , ( rect - > width < < 16 ) | rect - > height ) ;
PUSH_KICK ( push ) ;
2010-10-05 16:41:29 +10:00
return 0 ;
2009-12-11 19:24:15 +10:00
}
2010-10-05 16:41:29 +10:00
int
2009-12-11 19:24:15 +10:00
nv04_fbcon_imageblit ( struct fb_info * info , const struct fb_image * image )
{
2010-03-30 05:34:14 +00:00
struct nouveau_fbdev * nfbdev = info - > par ;
2016-11-04 17:20:35 +10:00
struct nouveau_drm * drm = nouveau_drm ( nfbdev - > helper . dev ) ;
2012-07-20 08:17:34 +10:00
struct nouveau_channel * chan = drm - > channel ;
2020-06-22 11:22:28 +10:00
struct nvif_push * push = chan - > chan . push ;
2009-12-11 19:24:15 +10:00
uint32_t fg ;
uint32_t bg ;
uint32_t dsize ;
uint32_t * data = ( uint32_t * ) image - > data ;
2010-10-05 16:41:29 +10:00
int ret ;
2009-12-11 19:24:15 +10:00
2010-10-05 16:41:29 +10:00
if ( image - > depth ! = 1 )
return - ENODEV ;
2009-12-11 19:24:15 +10:00
2020-06-22 11:22:28 +10:00
ret = PUSH_WAIT ( push , 8 ) ;
2010-10-05 16:41:29 +10:00
if ( ret )
return ret ;
2009-12-11 19:24:15 +10:00
if ( info - > fix . visual = = FB_VISUAL_TRUECOLOR | |
info - > fix . visual = = FB_VISUAL_DIRECTCOLOR ) {
fg = ( ( uint32_t * ) info - > pseudo_palette ) [ image - > fg_color ] ;
bg = ( ( uint32_t * ) info - > pseudo_palette ) [ image - > bg_color ] ;
} else {
fg = image - > fg_color ;
bg = image - > bg_color ;
}
2020-06-22 11:22:28 +10:00
PUSH_NVSQ ( push , NV04A , 0x0be4 , ( image - > dy < < 16 ) | ( image - > dx & 0xffff ) ,
0x0be8 , ( ( image - > dy + image - > height ) < < 16 ) |
( ( image - > dx + image - > width ) & 0xffff ) ,
0x0bec , bg ,
0x0bf0 , fg ,
0x0bf4 , ( image - > height < < 16 ) | ALIGN ( image - > width , 8 ) ,
0x0bf8 , ( image - > height < < 16 ) | image - > width ,
0x0bfc , ( image - > dy < < 16 ) | ( image - > dx & 0xffff ) ) ;
2009-12-11 19:24:15 +10:00
2016-07-28 18:56:13 -04:00
dsize = ALIGN ( ALIGN ( image - > width , 8 ) * image - > height , 32 ) > > 5 ;
2009-12-11 19:24:15 +10:00
while ( dsize ) {
int iter_len = dsize > 128 ? 128 : dsize ;
2020-06-22 11:22:28 +10:00
ret = PUSH_WAIT ( push , iter_len + 1 ) ;
2010-10-05 16:41:29 +10:00
if ( ret )
return ret ;
2009-12-11 19:24:15 +10:00
2020-06-22 11:22:28 +10:00
PUSH_NVSQ ( push , NV04A , 0x0c00 , data , iter_len ) ;
2009-12-11 19:24:15 +10:00
data + = iter_len ;
dsize - = iter_len ;
}
2020-06-22 11:22:28 +10:00
PUSH_KICK ( push ) ;
2010-10-05 16:41:29 +10:00
return 0 ;
2009-12-11 19:24:15 +10:00
}
int
nv04_fbcon_accel_init ( struct fb_info * info )
{
2010-03-30 05:34:14 +00:00
struct nouveau_fbdev * nfbdev = info - > par ;
2016-11-04 17:20:35 +10:00
struct drm_device * dev = nfbdev - > helper . dev ;
2012-07-31 16:16:21 +10:00
struct nouveau_drm * drm = nouveau_drm ( dev ) ;
2012-07-20 08:17:34 +10:00
struct nouveau_channel * chan = drm - > channel ;
2016-05-18 13:57:42 +10:00
struct nvif_device * device = & drm - > client . device ;
2020-06-22 11:08:51 +10:00
struct nvif_push * push = chan - > chan . push ;
2009-12-11 19:24:15 +10:00
int surface_fmt , pattern_fmt , rect_fmt ;
int ret ;
switch ( info - > var . bits_per_pixel ) {
case 8 :
surface_fmt = 1 ;
pattern_fmt = 3 ;
rect_fmt = 3 ;
break ;
case 16 :
surface_fmt = 4 ;
pattern_fmt = 1 ;
rect_fmt = 1 ;
break ;
case 32 :
switch ( info - > var . transp . length ) {
case 0 : /* depth 24 */
case 8 : /* depth 32 */
break ;
default :
return - EINVAL ;
}
surface_fmt = 6 ;
pattern_fmt = 3 ;
rect_fmt = 3 ;
break ;
default :
return - EINVAL ;
}
2020-03-30 09:51:33 +10:00
ret = nvif_object_ctor ( & chan - > user , " fbconCtxSurf2d " , 0x0062 ,
2014-08-10 04:10:22 +10:00
device - > info . family > = NV_DEVICE_INFO_V0_CELSIUS ?
0x0062 : 0x0042 , NULL , 0 , & nfbdev - > surf2d ) ;
2009-12-11 19:24:15 +10:00
if ( ret )
return ret ;
2020-03-30 09:51:33 +10:00
ret = nvif_object_ctor ( & chan - > user , " fbconCtxClip " , 0x0019 , 0x0019 ,
NULL , 0 , & nfbdev - > clip ) ;
2009-12-11 19:24:15 +10:00
if ( ret )
return ret ;
2020-03-30 09:51:33 +10:00
ret = nvif_object_ctor ( & chan - > user , " fbconCtxRop " , 0x0043 , 0x0043 ,
NULL , 0 , & nfbdev - > rop ) ;
2009-12-11 19:24:15 +10:00
if ( ret )
return ret ;
2020-03-30 09:51:33 +10:00
ret = nvif_object_ctor ( & chan - > user , " fbconCtxPatt " , 0x0044 , 0x0044 ,
NULL , 0 , & nfbdev - > patt ) ;
2009-12-11 19:24:15 +10:00
if ( ret )
return ret ;
2020-03-30 09:51:33 +10:00
ret = nvif_object_ctor ( & chan - > user , " fbconGdiRectText " , 0x004a , 0x004a ,
NULL , 0 , & nfbdev - > gdi ) ;
2009-12-11 19:24:15 +10:00
if ( ret )
return ret ;
2020-03-30 09:51:33 +10:00
ret = nvif_object_ctor ( & chan - > user , " fbconImageBlit " , 0x005f ,
2014-08-10 04:10:22 +10:00
device - > info . chipset > = 0x11 ? 0x009f : 0x005f ,
NULL , 0 , & nfbdev - > blit ) ;
2009-12-11 19:24:15 +10:00
if ( ret )
return ret ;
2020-06-22 11:08:51 +10:00
if ( PUSH_WAIT ( push , 49 + ( device - > info . chipset > = 0x11 ? 4 : 0 ) ) ) {
2010-01-04 19:25:09 +01:00
nouveau_fbcon_gpu_lockup ( info ) ;
2009-12-11 19:24:15 +10:00
return 0 ;
}
2020-06-22 11:08:51 +10:00
PUSH_NVSQ ( push , NV042 , 0x0000 , nfbdev - > surf2d . handle ) ;
PUSH_NVSQ ( push , NV042 , 0x0184 , chan - > vram . handle ,
0x0188 , chan - > vram . handle ) ;
PUSH_NVSQ ( push , NV042 , 0x0300 , surface_fmt ,
0x0304 , info - > fix . line_length | ( info - > fix . line_length < < 16 ) ,
0x0308 , info - > fix . smem_start - dev - > mode_config . fb_base ,
0x030c , info - > fix . smem_start - dev - > mode_config . fb_base ) ;
PUSH_NVSQ ( push , NV043 , 0x0000 , nfbdev - > rop . handle ) ;
PUSH_NVSQ ( push , NV043 , 0x0300 , 0x55 ) ;
PUSH_NVSQ ( push , NV044 , 0x0000 , nfbdev - > patt . handle ) ;
PUSH_NVSQ ( push , NV044 , 0x0300 , pattern_fmt ,
2009-12-11 19:24:15 +10:00
# ifdef __BIG_ENDIAN
2020-06-22 11:08:51 +10:00
0x0304 , 2 ,
2009-12-11 19:24:15 +10:00
# else
2020-06-22 11:08:51 +10:00
0x0304 , 1 ,
2009-12-11 19:24:15 +10:00
# endif
2020-06-22 11:08:51 +10:00
0x0308 , 0 ,
0x030c , 1 ,
0x0310 , ~ 0 ,
0x0314 , ~ 0 ,
0x0318 , ~ 0 ,
0x031c , ~ 0 ) ;
PUSH_NVSQ ( push , NV019 , 0x0000 , nfbdev - > clip . handle ) ;
PUSH_NVSQ ( push , NV019 , 0x0300 , 0 ,
0x0304 , ( info - > var . yres_virtual < < 16 ) | info - > var . xres_virtual ) ;
PUSH_NVSQ ( push , NV05F , 0x0000 , nfbdev - > blit . handle ) ;
PUSH_NVSQ ( push , NV05F , 0x019c , nfbdev - > surf2d . handle ) ;
PUSH_NVSQ ( push , NV05F , 0x02fc , 3 ) ;
if ( nfbdev - > blit . oclass = = 0x009f ) {
PUSH_NVSQ ( push , NV09F , 0x0120 , 0 ,
0x0124 , 1 ,
0x0128 , 2 ) ;
2013-11-11 13:59:40 +10:00
}
2009-12-11 19:24:15 +10:00
2020-06-22 11:08:51 +10:00
PUSH_NVSQ ( push , NV04A , 0x0000 , nfbdev - > gdi . handle ) ;
PUSH_NVSQ ( push , NV04A , 0x0198 , nfbdev - > surf2d . handle ) ;
PUSH_NVSQ ( push , NV04A , 0x0188 , nfbdev - > patt . handle ,
0x018c , nfbdev - > rop . handle ) ;
PUSH_NVSQ ( push , NV04A , 0x0304 , 1 ) ;
PUSH_NVSQ ( push , NV04A , 0x0300 , rect_fmt ) ;
PUSH_NVSQ ( push , NV04A , 0x02fc , 3 ) ;
2009-12-11 19:24:15 +10:00
2020-06-22 11:08:51 +10:00
PUSH_KICK ( push ) ;
2009-12-11 19:24:15 +10:00
return 0 ;
}