1 /*
2  * Copyright (C) 2006 Claudio Ciccani <klan@users.sf.net>
3  *
4  * Graphics driver for ATI Radeon cards written by
5  *             Claudio Ciccani <klan@users.sf.net>.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  *
21  */
22 
23 #include <config.h>
24 
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <unistd.h>
29 #include <time.h>
30 
31 #include <directfb.h>
32 
33 #include <core/coredefs.h>
34 #include <core/gfxcard.h>
35 #include <core/screens.h>
36 #include <core/layers.h>
37 #include <core/layer_context.h>
38 #include <core/layer_region.h>
39 #include <core/layer_control.h>
40 #include <core/layers_internal.h>
41 #include <core/palette.h>
42 #include <core/surface.h>
43 #include <core/system.h>
44 
45 #include <misc/conf.h>
46 
47 #include <gfx/convert.h>
48 
49 #include <direct/types.h>
50 #include <direct/messages.h>
51 #include <direct/util.h>
52 
53 #include "radeon.h"
54 #include "radeon_regs.h"
55 #include "radeon_mmio.h"
56 
57 
58 typedef struct {
59      CoreLayerRegionConfig  config;
60      CorePalette           *palette;
61      DFBColorAdjustment     adjustment;
62 
63      unsigned int           pll_max_freq;
64      unsigned int           pll_min_freq;
65      unsigned int           pll_ref_div;
66      unsigned int           pll_ref_clk;
67 
68      struct {
69           unsigned int      size;
70           u8                r[256];
71           u8                g[256];
72           u8                b[256];
73      } lut;
74 
75      struct {
76           u32 rCRTC2_GEN_CNTL;
77           u32 rFP2_GEN_CNTL;
78           u32 rDAC_CNTL2;
79           u32 rTV_DAC_CNTL;
80           u32 rDISP_OUTPUT_CNTL;
81           u32 rDISP_HW_DEBUG;
82           u32 rCRTC2_OFFSET_CNTL;
83      } save;
84 
85      struct {
86           u32 rCRTC2_GEN_CNTL;
87           u32 rDAC_CNTL2;
88           u32 rTV_DAC_CNTL;
89           u32 rDISP_OUTPUT_CNTL;
90           u32 rDISP_HW_DEBUG;
91           u32 rCRTC2_H_TOTAL_DISP;
92           u32 rCRTC2_H_SYNC_STRT_WID;
93           u32 rCRTC2_V_TOTAL_DISP;
94           u32 rCRTC2_V_SYNC_STRT_WID;
95           u32 rCRTC2_BASE_ADDR;
96           u32 rCRTC2_OFFSET;
97           u32 rCRTC2_OFFSET_CNTL;
98           u32 rCRTC2_PITCH;
99           u32 rFP2_GEN_CNTL;
100           u32 rFP2_H_SYNC_STRT_WID;
101           u32 rFP2_V_SYNC_STRT_WID;
102           u32 rP2PLL_REF_DIV;
103           u32 rP2PLL_DIV_0;
104           u32 rHTOTAL2_CNTL;
105      } regs;
106 } RadeonCrtc2LayerData;
107 
108 static VideoMode*  crtc2_find_mode    ( RadeonDriverData     *drv,
109                                         int                   xres,
110                                         int                   yres );
111 static bool        crtc2_calc_regs    ( RadeonDriverData      *rdrv,
112                                         RadeonCrtc2LayerData  *rcrtc2,
113                                         CoreLayerRegionConfig *config,
114                                         CoreSurface           *surface,
115                                         CoreSurfaceBufferLock *lock );
116 static void        crtc2_set_regs     ( RadeonDriverData      *rdrv,
117                                         RadeonCrtc2LayerData  *rcrtc2 );
118 static void        crtc2_calc_palette ( RadeonDriverData      *rdrv,
119                                         RadeonCrtc2LayerData  *rcrtc2,
120                                         CoreLayerRegionConfig *config,
121                                         DFBColorAdjustment    *adjustment,
122                                         CorePalette           *palette );
123 static void        crtc2_set_palette  ( RadeonDriverData      *rdrv,
124                                         RadeonCrtc2LayerData  *rcrtc2 );
125 
126 /*************************** CRTC2 Screen functions **************************/
127 
128 static DFBResult
crtc2InitScreen(CoreScreen * screen,CoreGraphicsDevice * device,void * driver_data,void * screen_data,DFBScreenDescription * description)129 crtc2InitScreen( CoreScreen           *screen,
130                  CoreGraphicsDevice   *device,
131                  void                 *driver_data,
132                  void                 *screen_data,
133                  DFBScreenDescription *description )
134 {
135      /* Set the screen capabilities. */
136      description->caps = DSCCAPS_VSYNC | DSCCAPS_POWER_MANAGEMENT;
137 
138      /* Set the screen name. */
139      snprintf( description->name,
140                DFB_SCREEN_DESC_NAME_LENGTH, "Radeon CRTC2" );
141 
142      return DFB_OK;
143 }
144 
145 static DFBResult
crtc2SetPowerMode(CoreScreen * screen,void * driver_data,void * screen_data,DFBScreenPowerMode mode)146 crtc2SetPowerMode( CoreScreen         *screen,
147                    void               *driver_data,
148                    void               *screen_data,
149                    DFBScreenPowerMode  mode )
150 {
151      RadeonDriverData *rdrv          = (RadeonDriverData*) driver_data;
152      volatile u8      *mmio          = rdrv->mmio_base;
153      u32               crtc2_gen_cntl;
154 
155      crtc2_gen_cntl  = radeon_in32( mmio, CRTC2_GEN_CNTL );
156      crtc2_gen_cntl &= ~(CRTC2_HSYNC_DIS | CRTC2_VSYNC_DIS | CRTC2_DISP_DIS);
157 
158      switch (mode) {
159           case DSPM_OFF:
160                crtc2_gen_cntl |= CRTC2_HSYNC_DIS |
161                                  CRTC2_VSYNC_DIS |
162                                  CRTC2_DISP_DIS;
163                break;
164           case DSPM_SUSPEND:
165                crtc2_gen_cntl |= CRTC2_VSYNC_DIS |
166                                  CRTC2_DISP_DIS;
167                break;
168           case DSPM_STANDBY:
169                crtc2_gen_cntl |= CRTC2_HSYNC_DIS |
170                                  CRTC2_DISP_DIS;
171                break;
172           case DSPM_ON:
173                break;
174           default:
175                D_DEBUG( "unknown power mode" );
176                return DFB_INVARG;
177      }
178 
179      radeon_out32( mmio, CRTC2_GEN_CNTL, crtc2_gen_cntl );
180 
181      return DFB_OK;
182 }
183 
184 static DFBResult
crtc2WaitVSync(CoreScreen * screen,void * driver_data,void * screen_data)185 crtc2WaitVSync( CoreScreen *screen,
186                 void       *driver_data,
187                 void       *screen_data )
188 {
189      RadeonDriverData *rdrv = (RadeonDriverData*) driver_data;
190      volatile u8      *mmio = rdrv->mmio_base;
191      int               i;
192 
193      if (dfb_config->pollvsync_none)
194           return DFB_OK;
195 
196      radeon_out32( mmio, GEN_INT_STATUS,
197           (radeon_in32( mmio, GEN_INT_STATUS ) & ~VSYNC2_INT) | VSYNC2_INT_AK );
198 
199      for (i = 0; i < 2000000; i++) {
200           struct timespec t = { 0, 10000 };
201 
202           if (radeon_in32( mmio, GEN_INT_STATUS ) & VSYNC2_INT)
203                break;
204           nanosleep( &t, NULL );
205      }
206 
207      return DFB_OK;
208 }
209 
210 static DFBResult
crtc2GetScreenSize(CoreScreen * screen,void * driver_data,void * screen_data,int * ret_width,int * ret_height)211 crtc2GetScreenSize( CoreScreen *screen,
212                     void       *driver_data,
213                     void       *screen_data,
214                     int        *ret_width,
215                     int        *ret_height )
216 {
217      RadeonDriverData *rdrv = (RadeonDriverData*) driver_data;
218      volatile u8      *mmio = rdrv->mmio_base;
219      unsigned int      xres;
220      unsigned int      yres;
221 
222      xres = ((radeon_in32( mmio, CRTC2_H_TOTAL_DISP ) >> 16) + 1) * 8;
223      yres = ((radeon_in32( mmio, CRTC2_V_TOTAL_DISP ) >> 16) + 1);
224 
225      D_DEBUG( "DirectFB/Radeon/CRTC2: "
226               "detected screen size %dx%d.\n", xres, yres );
227 
228      if (xres <= 1 || yres <= 1) {
229           VideoMode *mode = dfb_system_modes();
230 
231           if (!mode) {
232                D_WARN( "no default video mode" );
233                return DFB_UNSUPPORTED;
234           }
235           xres = mode->xres;
236           yres = mode->yres;
237      }
238 
239      *ret_width  = xres;
240      *ret_height = yres;
241 
242      return DFB_OK;
243 }
244 
245 ScreenFuncs RadeonCrtc2ScreenFuncs = {
246      .InitScreen    = crtc2InitScreen,
247      .SetPowerMode  = crtc2SetPowerMode,
248      .WaitVSync     = crtc2WaitVSync,
249      .GetScreenSize = crtc2GetScreenSize
250 };
251 
252 /**************************** CRTC2 Layer functions **************************/
253 
254 #define CRTC2_SUPPORTED_OPTIONS ( DLOP_ALPHACHANNEL )
255 
256 static int
crtc2LayerDataSize(void)257 crtc2LayerDataSize( void )
258 {
259      return sizeof(RadeonCrtc2LayerData);
260 }
261 
262 static DFBResult
crtc2InitLayer(CoreLayer * layer,void * driver_data,void * layer_data,DFBDisplayLayerDescription * description,DFBDisplayLayerConfig * config,DFBColorAdjustment * adjustment)263 crtc2InitLayer( CoreLayer                  *layer,
264                 void                       *driver_data,
265                 void                       *layer_data,
266                 DFBDisplayLayerDescription *description,
267                 DFBDisplayLayerConfig      *config,
268                 DFBColorAdjustment         *adjustment )
269 {
270      RadeonDriverData     *rdrv   = (RadeonDriverData*) driver_data;
271      RadeonCrtc2LayerData *rcrtc2 = (RadeonCrtc2LayerData*) layer_data;
272      volatile u8          *mmio   = rdrv->mmio_base;
273      VideoMode            *mode;
274 
275      mode = dfb_system_modes();
276      if (!mode) {
277           D_BUG( "no default video mode" );
278           return DFB_FAILURE;
279      }
280 
281      /* Fill layer description. */
282      description->caps = DLCAPS_SURFACE     | DLCAPS_BRIGHTNESS |
283                          DLCAPS_CONTRAST    | DLCAPS_SATURATION |
284                          DLCAPS_ALPHACHANNEL;
285 
286      description->type = DLTF_GRAPHICS;
287 
288      snprintf( description->name,
289                DFB_DISPLAY_LAYER_DESC_NAME_LENGTH, "Radeon CRTC2's Underlay" );
290 
291      /* Set default configuration. */
292      config->flags       = DLCONF_WIDTH       | DLCONF_HEIGHT     |
293                            DLCONF_PIXELFORMAT | DLCONF_BUFFERMODE |
294                            DLCONF_OPTIONS;
295      config->width       = mode->xres;
296      config->height      = mode->yres;
297      config->pixelformat = DSPF_RGB16;
298      config->buffermode  = DLBM_FRONTONLY;
299      config->options     = DLOP_NONE;
300 
301      /* Set default color adjustment. */
302      adjustment->flags      = DCAF_BRIGHTNESS | DCAF_CONTRAST |
303                               DCAF_SATURATION;
304      adjustment->brightness = 0x8000;
305      adjustment->contrast   = 0x8000;
306      adjustment->saturation = 0x8000;
307 
308      /* Set PLL coefficients (should be done by reading the BIOS). */
309      rcrtc2->pll_max_freq = 35000;
310      rcrtc2->pll_min_freq = 12000;
311      rcrtc2->pll_ref_div  = 60;
312      rcrtc2->pll_ref_clk  = 2700;
313 
314      /* Save common registers. */
315      rcrtc2->save.rCRTC2_GEN_CNTL = radeon_in32( mmio, CRTC2_GEN_CNTL );
316      rcrtc2->save.rFP2_GEN_CNTL = radeon_in32( mmio, FP2_GEN_CNTL );
317      rcrtc2->save.rDAC_CNTL2 = radeon_in32( mmio, DAC_CNTL2 );
318      rcrtc2->save.rTV_DAC_CNTL = radeon_in32( mmio, TV_DAC_CNTL );
319      rcrtc2->save.rDISP_OUTPUT_CNTL = radeon_in32( mmio, DISP_OUTPUT_CNTL );
320      rcrtc2->save.rDISP_HW_DEBUG = radeon_in32( mmio, DISP_HW_DEBUG );
321      rcrtc2->save.rCRTC2_OFFSET_CNTL = radeon_in32( mmio, CRTC2_OFFSET_CNTL );
322 
323      return DFB_OK;
324 }
325 
326 static DFBResult
crtc2TestRegion(CoreLayer * layer,void * driver_data,void * layer_data,CoreLayerRegionConfig * config,CoreLayerRegionConfigFlags * failed)327 crtc2TestRegion( CoreLayer                  *layer,
328                  void                       *driver_data,
329                  void                       *layer_data,
330                  CoreLayerRegionConfig      *config,
331                  CoreLayerRegionConfigFlags *failed )
332 {
333      RadeonDriverData           *rdrv = (RadeonDriverData*) driver_data;
334      CoreLayerRegionConfigFlags  fail = 0;
335 
336      /* check for unsupported options */
337      if (config->options & ~CRTC2_SUPPORTED_OPTIONS)
338           fail |= CLRCF_OPTIONS;
339 
340      if (config->options & DLOP_ALPHACHANNEL && config->format != DSPF_ARGB)
341           fail |= CLRCF_OPTIONS;
342 
343      /* check for unsupported buffermode */
344      switch (config->buffermode) {
345           case DLBM_FRONTONLY:
346           case DLBM_BACKSYSTEM:
347           case DLBM_BACKVIDEO:
348           case DLBM_TRIPLE:
349                break;
350 
351           default:
352                fail |= CLRCF_BUFFERMODE;
353                break;
354      }
355 
356      /* check for unsupported pixelformat */
357      switch (config->format) {
358           case DSPF_LUT8:
359           case DSPF_RGB332:
360           case DSPF_RGB555:
361           case DSPF_ARGB1555:
362           case DSPF_RGB16:
363           case DSPF_RGB24:
364           case DSPF_RGB32:
365           case DSPF_ARGB:
366                break;
367 
368           default:
369                fail |= CLRCF_FORMAT;
370                break;
371      }
372 
373      /* check for unsupported size */
374      if (!crtc2_find_mode( rdrv, config->width, config->height ))
375           fail |= CLRCF_WIDTH | CLRCF_HEIGHT;
376 
377      if (failed)
378           *failed = fail;
379 
380      return fail ? DFB_UNSUPPORTED : DFB_OK;
381 }
382 
383 static DFBResult
crtc2AddRegion(CoreLayer * layer,void * driver_data,void * layer_data,void * region_data,CoreLayerRegionConfig * config)384 crtc2AddRegion( CoreLayer             *layer,
385                 void                  *driver_data,
386                 void                  *layer_data,
387                 void                  *region_data,
388                 CoreLayerRegionConfig *config )
389 {
390      RadeonDriverData *rdrv = (RadeonDriverData*) driver_data;
391      RadeonDeviceData *rdev = rdrv->device_data;
392 
393      if (!rdev->monitor2) {
394           D_ERROR( "DirectFB/Radeon/CRTC2: "
395                    "no secondary monitor connected!\n" );
396           return DFB_IO;
397      }
398 
399      return DFB_OK;
400 }
401 
402 static DFBResult
crtc2SetRegion(CoreLayer * layer,void * driver_data,void * layer_data,void * region_data,CoreLayerRegionConfig * config,CoreLayerRegionConfigFlags updated,CoreSurface * surface,CorePalette * palette,CoreSurfaceBufferLock * lock)403 crtc2SetRegion( CoreLayer                  *layer,
404                 void                       *driver_data,
405                 void                       *layer_data,
406                 void                       *region_data,
407                 CoreLayerRegionConfig      *config,
408                 CoreLayerRegionConfigFlags  updated,
409                 CoreSurface                *surface,
410                 CorePalette                *palette,
411                 CoreSurfaceBufferLock      *lock )
412 {
413      RadeonDriverData     *rdrv   = (RadeonDriverData*) driver_data;
414      RadeonCrtc2LayerData *rcrtc2 = (RadeonCrtc2LayerData*) layer_data;
415 
416      rcrtc2->config  = *config;
417      rcrtc2->palette = palette;
418 
419      updated &= CLRCF_WIDTH  | CLRCF_HEIGHT  |
420                 CLRCF_FORMAT | CLRCF_SURFACE | CLRCF_PALETTE;
421 
422      if (updated & ~CLRCF_PALETTE) {
423           if (!crtc2_calc_regs( rdrv, rcrtc2, &rcrtc2->config, surface, lock ))
424                return DFB_UNSUPPORTED;
425 
426           crtc2_set_regs( rdrv, rcrtc2 );
427      }
428 
429      if (updated) {
430           crtc2_calc_palette( rdrv, rcrtc2, &rcrtc2->config,
431                               &rcrtc2->adjustment, rcrtc2->palette );
432           crtc2_set_palette( rdrv, rcrtc2 );
433      }
434 
435      return DFB_OK;
436 }
437 
438 static DFBResult
crtc2RemoveRegion(CoreLayer * layer,void * driver_data,void * layer_data,void * region_data)439 crtc2RemoveRegion( CoreLayer *layer,
440                    void      *driver_data,
441                    void      *layer_data,
442                    void      *region_data )
443 {
444      RadeonDriverData     *rdrv   = (RadeonDriverData*) driver_data;
445      RadeonCrtc2LayerData *rcrtc2 = (RadeonCrtc2LayerData*) layer_data;
446      volatile u8          *mmio   = rdrv->mmio_base;
447 
448      radeon_waitidle( rdrv, rdrv->device_data );
449 
450      radeon_out32( mmio, CRTC2_GEN_CNTL, rcrtc2->save.rCRTC2_GEN_CNTL );
451      radeon_out32( mmio, FP2_GEN_CNTL, rcrtc2->save.rFP2_GEN_CNTL );
452      radeon_out32( mmio, DAC_CNTL2, rcrtc2->save.rDAC_CNTL2 );
453      radeon_out32( mmio, TV_DAC_CNTL, rcrtc2->save.rTV_DAC_CNTL );
454      radeon_out32( mmio, DISP_OUTPUT_CNTL, rcrtc2->save.rDISP_OUTPUT_CNTL );
455      radeon_out32( mmio, DISP_HW_DEBUG, rcrtc2->save.rDISP_HW_DEBUG );
456      radeon_out32( mmio, CRTC2_OFFSET_CNTL, rcrtc2->save.rCRTC2_OFFSET_CNTL );
457 
458      return DFB_OK;
459 }
460 
461 static DFBResult
crtc2FlipRegion(CoreLayer * layer,void * driver_data,void * layer_data,void * region_data,CoreSurface * surface,DFBSurfaceFlipFlags flags,CoreSurfaceBufferLock * lock)462 crtc2FlipRegion( CoreLayer             *layer,
463                  void                  *driver_data,
464                  void                  *layer_data,
465                  void                  *region_data,
466                  CoreSurface           *surface,
467                  DFBSurfaceFlipFlags    flags,
468                  CoreSurfaceBufferLock *lock )
469 {
470      RadeonDriverData     *rdrv   = (RadeonDriverData*) driver_data;
471      RadeonDeviceData     *rdev   = rdrv->device_data;
472      RadeonCrtc2LayerData *rcrtc2 = (RadeonCrtc2LayerData*) layer_data;
473      volatile u8          *mmio   = rdrv->mmio_base;
474 
475      if (lock->phys - lock->offset == rdev->fb_phys)
476           rcrtc2->regs.rCRTC2_BASE_ADDR = rdev->fb_offset;
477      else
478           rcrtc2->regs.rCRTC2_BASE_ADDR = rdev->agp_offset;
479 
480      rcrtc2->regs.rCRTC2_OFFSET = lock->offset;
481 
482      radeon_waitidle( rdrv, rdrv->device_data );
483 
484      radeon_out32( mmio, CRTC2_BASE_ADDR, rcrtc2->regs.rCRTC2_BASE_ADDR );
485      radeon_out32( mmio, CRTC2_OFFSET, rcrtc2->regs.rCRTC2_OFFSET );
486 
487      dfb_surface_flip( surface, false );
488 
489      if (flags & DSFLIP_WAIT)
490           dfb_layer_wait_vsync( layer );
491 
492      return DFB_OK;
493 }
494 
495 static DFBResult
crtc2SetColorAdjustment(CoreLayer * layer,void * driver_data,void * layer_data,DFBColorAdjustment * adj)496 crtc2SetColorAdjustment( CoreLayer          *layer,
497                          void               *driver_data,
498                          void               *layer_data,
499                          DFBColorAdjustment *adj )
500 {
501      RadeonDriverData     *rdrv   = (RadeonDriverData*) driver_data;
502      RadeonCrtc2LayerData *rcrtc2 = (RadeonCrtc2LayerData*) layer_data;
503 
504      if (adj->flags & DCAF_BRIGHTNESS) {
505           if (adj->brightness == 0x8000) {
506                rcrtc2->adjustment.flags &= ~DCAF_BRIGHTNESS;
507           } else {
508                rcrtc2->adjustment.flags |= DCAF_BRIGHTNESS;
509                rcrtc2->adjustment.brightness = adj->brightness;
510           }
511      }
512      if (adj->flags & DCAF_CONTRAST) {
513           if (adj->contrast == 0x8000) {
514                rcrtc2->adjustment.flags &= ~DCAF_CONTRAST;
515           } else {
516                rcrtc2->adjustment.flags |= DCAF_CONTRAST;
517                rcrtc2->adjustment.contrast = adj->contrast;
518           }
519      }
520      if (adj->flags & DCAF_SATURATION) {
521           if (adj->saturation == 0x8000) {
522                rcrtc2->adjustment.flags &= ~DCAF_SATURATION;
523           } else {
524                rcrtc2->adjustment.flags |= DCAF_SATURATION;
525                rcrtc2->adjustment.saturation = adj->saturation;
526           }
527      }
528 
529      crtc2_calc_palette( rdrv, rcrtc2, &rcrtc2->config,
530                          &rcrtc2->adjustment, rcrtc2->palette );
531      crtc2_set_palette( rdrv, rcrtc2 );
532 
533      return DFB_OK;
534 }
535 
536 DisplayLayerFuncs RadeonCrtc2LayerFuncs = {
537      .LayerDataSize      = crtc2LayerDataSize,
538      .InitLayer          = crtc2InitLayer,
539      .TestRegion         = crtc2TestRegion,
540      .AddRegion          = crtc2AddRegion,
541      .SetRegion          = crtc2SetRegion,
542      .RemoveRegion       = crtc2RemoveRegion,
543      .FlipRegion         = crtc2FlipRegion,
544      .SetColorAdjustment = crtc2SetColorAdjustment
545 };
546 
547 /************************** CRTC2 internal functions *************************/
548 
549 static VideoMode*
crtc2_find_mode(RadeonDriverData * rdrv,int xres,int yres)550 crtc2_find_mode( RadeonDriverData *rdrv,
551                  int               xres,
552                  int               yres )
553 {
554      VideoMode *modes = dfb_system_modes();
555      VideoMode *mode;
556 
557      for (mode = modes; mode; mode = mode->next) {
558           if (mode->xres == xres && mode->yres == yres)
559                return mode;
560      }
561 
562      return NULL;
563 }
564 
565 static void
crtc2_calc_pllregs(RadeonDriverData * rdrv,RadeonCrtc2LayerData * rcrtc2,unsigned int freq)566 crtc2_calc_pllregs( RadeonDriverData     *rdrv,
567                     RadeonCrtc2LayerData *rcrtc2,
568                     unsigned int          freq )
569 {
570      struct {
571           int divider;
572           int bitvalue;
573      } *post_div, post_divs[] = {
574           {  1, 0 }, /* VCLK_SRC    */
575           {  2, 1 }, /* VCLK_SRC/2  */
576           {  4, 2 }, /* VCLK_SRC/4  */
577           {  8, 3 }, /* VCLK_SRC/8  */
578           {  3, 4 }, /* VCLK_SRC/3  */
579           {  6, 6 }, /* VCLK_SRC/6  */
580           { 12, 7 }, /* VCLK_SRC/12 */
581           {  0, 0 }
582      };
583      u32 pll_output_freq_2 = 0;
584      u32 feedback_div_2;
585 
586      if (freq > rcrtc2->pll_max_freq)
587           freq = rcrtc2->pll_max_freq;
588      if (freq*12 < rcrtc2->pll_min_freq)
589           freq = rcrtc2->pll_min_freq/12;
590 
591      for (post_div = &post_divs[0]; post_div->divider; ++post_div) {
592           pll_output_freq_2 = post_div->divider * freq;
593           if (pll_output_freq_2 >= rcrtc2->pll_min_freq &&
594               pll_output_freq_2 <= rcrtc2->pll_max_freq)
595                break;
596      }
597 
598      if (!post_div->divider) {
599           pll_output_freq_2 = freq;
600           post_div = &post_divs[0];
601      }
602 
603      feedback_div_2  = rcrtc2->pll_ref_div * pll_output_freq_2;
604      feedback_div_2 += rcrtc2->pll_ref_clk/2;
605      feedback_div_2 /= rcrtc2->pll_ref_clk;
606 
607      D_DEBUG( "DirectFB/Radeon/CRTC2: "
608               "DotCLock=%d OutputFreq=%d FeedbackDiv=%d PostDiv=%d.\n",
609               freq, pll_output_freq_2, feedback_div_2, post_div->divider );
610 
611      rcrtc2->regs.rP2PLL_REF_DIV = rcrtc2->pll_ref_div;
612      rcrtc2->regs.rP2PLL_DIV_0   = feedback_div_2 | (post_div->bitvalue << 16);
613      rcrtc2->regs.rHTOTAL2_CNTL  = 0;
614 }
615 
616 static bool
crtc2_calc_regs(RadeonDriverData * rdrv,RadeonCrtc2LayerData * rcrtc2,CoreLayerRegionConfig * config,CoreSurface * surface,CoreSurfaceBufferLock * lock)617 crtc2_calc_regs( RadeonDriverData      *rdrv,
618                  RadeonCrtc2LayerData  *rcrtc2,
619                  CoreLayerRegionConfig *config,
620                  CoreSurface           *surface,
621                  CoreSurfaceBufferLock *lock )
622 {
623      RadeonDeviceData  *rdev   = rdrv->device_data;
624      VideoMode         *mode;
625      u32                format = 0;
626 
627      int   h_total, h_sync_start, h_sync_end, h_sync_wid;
628      int   v_total, v_sync_start, v_sync_end, v_sync_wid;
629 
630 
631      mode = crtc2_find_mode( rdrv, config->width, config->height );
632      if (!mode) {
633           D_BUG( "unexpected error while searching video mode" );
634           return false;
635      }
636 
637      switch (config->format) {
638           case DSPF_LUT8:
639           case DSPF_RGB332:
640                format = DST_8BPP;
641                break;
642           case DSPF_RGB555:
643           case DSPF_ARGB1555:
644                format = DST_15BPP;
645                break;
646           case DSPF_RGB16:
647                format = DST_16BPP;
648                break;
649           case DSPF_RGB24:
650                format = DST_24BPP;
651                break;
652           case DSPF_RGB32:
653           case DSPF_ARGB:
654                format = DST_32BPP;
655                break;
656           default:
657                D_BUG( "unexpected pixelformat" );
658                return false;
659      }
660 
661      h_sync_start = mode->xres + mode->right_margin;
662      h_sync_end   = h_sync_start + mode->hsync_len;
663      h_total      = h_sync_end + mode->left_margin;
664      h_sync_wid   = (h_sync_end - h_sync_start) / 8;
665      h_sync_wid   = CLAMP( h_sync_wid, 1, 0x3f );
666      h_sync_start = h_sync_start - 8;
667 
668      v_sync_start = mode->yres + mode->lower_margin;
669      v_sync_end   = v_sync_start + mode->vsync_len;
670      v_total      = v_sync_end + mode->upper_margin;
671      v_sync_wid   = v_sync_end - v_sync_start;
672      v_sync_wid   = CLAMP( v_sync_wid, 1, 0x1f );
673 
674      D_DEBUG( "DirectFB/Radeon/CRTC2: \n"
675               "\t\thSyncStart:%d hSyncEnd:%d hTotal:%d hSyncWid:%d\n"
676               "\t\tvSyncStart:%d vSyncEnd:%d vTotal:%d vSyncWid:%d\n",
677               h_sync_start, h_sync_end, h_total, h_sync_wid,
678               v_sync_start, v_sync_end, v_total, v_sync_wid );
679 
680      rcrtc2->regs.rCRTC2_GEN_CNTL = CRTC2_EN | CRTC2_CRT2_ON | (format << 8);
681      if (mode->laced)
682           rcrtc2->regs.rCRTC2_GEN_CNTL |= CRTC2_INTERLACE_EN;
683      if (mode->doubled)
684           rcrtc2->regs.rCRTC2_GEN_CNTL |= CRTC2_DBL_SCAN_EN;
685      if (mode->sync_on_green)
686           rcrtc2->regs.rCRTC2_GEN_CNTL |= CRTC2_CSYNC_EN;
687 
688      rcrtc2->regs.rDAC_CNTL2 = rcrtc2->save.rDAC_CNTL2 | DAC2_DAC2_CLK_SEL;
689      rcrtc2->regs.rTV_DAC_CNTL = 0x00280203;
690      rcrtc2->regs.rDISP_OUTPUT_CNTL = rcrtc2->save.rDISP_OUTPUT_CNTL;
691      rcrtc2->regs.rDISP_HW_DEBUG = rcrtc2->save.rDISP_HW_DEBUG;
692 
693      if (rdev->chipset == CHIP_UNKNOWN ||
694          rdev->chipset == CHIP_R200    ||
695          rdev->chipset >= CHIP_R300)
696      {
697           rcrtc2->regs.rDISP_OUTPUT_CNTL &= ~(DISP_DAC_SOURCE_MASK |
698                                               DISP_DAC2_SOURCE_MASK);
699 
700           /* If primary monitor is a TV monitor,
701            * reverse the DAC source to control it using the CRTC2. */
702           if (rdev->monitor1 == MT_CTV || rdev->monitor1 == MT_STV)
703                rcrtc2->regs.rDISP_OUTPUT_CNTL |= DISP_DAC2_SOURCE_CRTC2;
704           else
705                rcrtc2->regs.rDISP_OUTPUT_CNTL |= DISP_DAC_SOURCE_CRTC2;
706      }
707      else {
708           if (rdev->monitor1 == MT_CTV || rdev->monitor1 == MT_STV) {
709                rcrtc2->regs.rDISP_HW_DEBUG &= ~CRT2_DISP1_SEL;
710                rcrtc2->regs.rDAC_CNTL2     &= ~DAC2_DAC_CLK_SEL;
711           }
712           else {
713                rcrtc2->regs.rDISP_HW_DEBUG |= CRT2_DISP1_SEL;
714                rcrtc2->regs.rDAC_CNTL2     |= DAC2_DAC_CLK_SEL;
715           }
716      }
717 
718      rcrtc2->regs.rCRTC2_H_TOTAL_DISP = ((h_total/8 - 1) & 0x3ff) |
719                                         ((mode->xres/8 - 1) << 16);
720      rcrtc2->regs.rCRTC2_H_SYNC_STRT_WID = (h_sync_start & 0x1fff) |
721                                            ((h_sync_wid & 0x3f) << 16);
722      if (!mode->hsync_high)
723           rcrtc2->regs.rCRTC2_H_SYNC_STRT_WID |= CRTC2_H_SYNC_POL;
724 
725      rcrtc2->regs.rCRTC2_V_TOTAL_DISP = ((v_total - 1) & 0xffff) |
726                                         ((mode->yres - 1) << 16);
727      rcrtc2->regs.rCRTC2_V_SYNC_STRT_WID = ((v_sync_start - 1) & 0xfff) |
728                                            ((v_sync_wid & 0x1f) << 16);
729      if (!mode->vsync_high)
730           rcrtc2->regs.rCRTC2_V_SYNC_STRT_WID |= CRTC2_V_SYNC_POL;
731 
732      if (lock->phys - lock->offset == rdev->fb_phys)
733           rcrtc2->regs.rCRTC2_BASE_ADDR = rdev->fb_offset;
734      else
735           rcrtc2->regs.rCRTC2_BASE_ADDR = rdev->agp_offset;
736 
737      rcrtc2->regs.rCRTC2_OFFSET = lock->offset;
738 
739      rcrtc2->regs.rCRTC2_OFFSET_CNTL = rcrtc2->save.rCRTC2_OFFSET_CNTL;
740      rcrtc2->regs.rCRTC2_OFFSET_CNTL &= ~CRTC_TILE_EN;
741      rcrtc2->regs.rCRTC2_OFFSET_CNTL |= CRTC_HSYNC_EN;
742 
743      rcrtc2->regs.rCRTC2_PITCH  = (lock->pitch /
744                                    DFB_BYTES_PER_PIXEL(surface->config.format)) >> 3;
745      rcrtc2->regs.rCRTC2_PITCH |= rcrtc2->regs.rCRTC2_PITCH << 16;
746 
747      if (rdev->monitor2 == MT_DFP) {
748           rcrtc2->regs.rCRTC2_GEN_CNTL &= ~CRTC2_CRT2_ON;
749           rcrtc2->regs.rFP2_GEN_CNTL    = rcrtc2->save.rFP2_GEN_CNTL | FP2_ON;
750 
751           if (rdev->chipset == CHIP_UNKNOWN ||
752               rdev->chipset == CHIP_R200    ||
753               rdev->chipset >= CHIP_R300)
754           {
755                rcrtc2->regs.rFP2_GEN_CNTL &= ~(R200_FP2_SOURCE_SEL_MASK |
756                                                FP2_DVO_RATE_SEL_SDR);
757                rcrtc2->regs.rFP2_GEN_CNTL |= R200_FP2_SOURCE_SEL_CRTC2 | FP2_DVO_EN;
758           }
759           else {
760                rcrtc2->regs.rFP2_GEN_CNTL &= ~FP2_SRC_SEL_MASK;
761                rcrtc2->regs.rFP2_GEN_CNTL |= FP2_SRC_SEL_CRTC2;
762           }
763 
764           rcrtc2->regs.rFP2_H_SYNC_STRT_WID = rcrtc2->regs.rCRTC2_H_SYNC_STRT_WID;
765           rcrtc2->regs.rFP2_V_SYNC_STRT_WID = rcrtc2->regs.rCRTC2_V_SYNC_STRT_WID;
766      }
767      else {
768           rcrtc2->regs.rFP2_GEN_CNTL = rcrtc2->save.rFP2_GEN_CNTL;
769           rcrtc2->regs.rFP2_H_SYNC_STRT_WID = 0;
770           rcrtc2->regs.rFP2_V_SYNC_STRT_WID = 0;
771      }
772 
773      crtc2_calc_pllregs( rdrv, rcrtc2, 100000000 / mode->pixclock );
774 
775      return true;
776 }
777 
778 static void
crtc2_set_regs(RadeonDriverData * rdrv,RadeonCrtc2LayerData * rcrtc2)779 crtc2_set_regs ( RadeonDriverData     *rdrv,
780                  RadeonCrtc2LayerData *rcrtc2 )
781 {
782      volatile u8 *mmio = rdrv->mmio_base;
783      u32          tmp;
784 
785      /* Lock the card during mode switching. */
786      dfb_gfxcard_lock( GDLF_WAIT | GDLF_SYNC );
787 
788      radeon_out32( mmio, CRTC2_GEN_CNTL,
789                          rcrtc2->regs.rCRTC2_GEN_CNTL | CRTC2_DISP_DIS );
790 
791      radeon_out32( mmio, DAC_CNTL2, rcrtc2->regs.rDAC_CNTL2 );
792      radeon_out32( mmio, TV_DAC_CNTL, rcrtc2->regs.rTV_DAC_CNTL );
793      radeon_out32( mmio, DISP_OUTPUT_CNTL, rcrtc2->regs.rDISP_OUTPUT_CNTL );
794      radeon_out32( mmio, DISP_HW_DEBUG, rcrtc2->regs.rDISP_HW_DEBUG );
795 
796      radeon_out32( mmio, CRTC2_H_TOTAL_DISP, rcrtc2->regs.rCRTC2_H_TOTAL_DISP );
797      radeon_out32( mmio, CRTC2_H_SYNC_STRT_WID, rcrtc2->regs.rCRTC2_H_SYNC_STRT_WID );
798 
799      radeon_out32( mmio, CRTC2_V_TOTAL_DISP, rcrtc2->regs.rCRTC2_V_TOTAL_DISP );
800      radeon_out32( mmio, CRTC2_V_SYNC_STRT_WID, rcrtc2->regs.rCRTC2_V_SYNC_STRT_WID );
801 
802      radeon_out32( mmio, CRTC2_BASE_ADDR, rcrtc2->regs.rCRTC2_BASE_ADDR );
803      radeon_out32( mmio, CRTC2_OFFSET, rcrtc2->regs.rCRTC2_OFFSET );
804      radeon_out32( mmio, CRTC2_OFFSET_CNTL, rcrtc2->regs.rCRTC2_OFFSET_CNTL );
805      radeon_out32( mmio, CRTC2_PITCH, rcrtc2->regs.rCRTC2_PITCH );
806 
807      radeon_out32( mmio, FP2_GEN_CNTL, rcrtc2->regs.rFP2_GEN_CNTL );
808      radeon_out32( mmio, FP2_H_SYNC_STRT_WID, rcrtc2->regs.rFP2_H_SYNC_STRT_WID );
809      radeon_out32( mmio, FP2_V_SYNC_STRT_WID, rcrtc2->regs.rFP2_V_SYNC_STRT_WID );
810 
811      tmp = radeon_inpll( mmio, PIXCLKS_CNTL) & ~PIX2CLK_SRC_SEL_MASK;
812      radeon_outpll( mmio, PIXCLKS_CNTL, tmp | PIX2CLK_SRC_SEL_CPUCLK );
813 
814      tmp = radeon_inpll( mmio, P2PLL_CNTL );
815      radeon_outpll( mmio, P2PLL_CNTL, tmp | P2PLL_RESET |
816                                       P2PLL_ATOMIC_UPDATE_EN |
817                                       P2PLL_VGA_ATOMIC_UPDATE_EN );
818 
819      tmp = radeon_inpll( mmio, P2PLL_REF_DIV ) & ~P2PLL_REF_DIV_MASK;
820      radeon_outpll( mmio, P2PLL_REF_DIV, tmp | rcrtc2->regs.rP2PLL_REF_DIV );
821 
822      tmp = radeon_inpll( mmio, P2PLL_DIV_0 ) & ~P2PLL_FB0_DIV_MASK;
823      radeon_outpll( mmio, P2PLL_DIV_0, tmp | rcrtc2->regs.rP2PLL_DIV_0 );
824 
825      tmp = radeon_inpll( mmio, P2PLL_DIV_0 ) & ~P2PLL_POST0_DIV_MASK;
826      radeon_outpll( mmio, P2PLL_DIV_0, tmp | rcrtc2->regs.rP2PLL_DIV_0 );
827 
828      while (radeon_inpll( mmio, P2PLL_REF_DIV ) & P2PLL_ATOMIC_UPDATE_R);
829 
830      radeon_outpll( mmio, P2PLL_REF_DIV,
831                     radeon_inpll( mmio, P2PLL_REF_DIV ) | P2PLL_ATOMIC_UPDATE_W );
832 
833      for (tmp = 0; tmp < 1000; tmp++) {
834           if (!(radeon_inpll( mmio, P2PLL_REF_DIV ) & P2PLL_ATOMIC_UPDATE_R))
835                break;
836      }
837 
838      radeon_outpll( mmio, HTOTAL2_CNTL, rcrtc2->regs.rHTOTAL2_CNTL );
839 
840      tmp = radeon_inpll( mmio, P2PLL_CNTL );
841      radeon_outpll( mmio, P2PLL_CNTL, tmp & ~(P2PLL_RESET | P2PLL_SLEEP |
842                                               P2PLL_ATOMIC_UPDATE_EN |
843                                               P2PLL_VGA_ATOMIC_UPDATE_EN) );
844 
845      usleep( 5000 );
846 
847      tmp = radeon_inpll( mmio, PIXCLKS_CNTL ) & ~PIX2CLK_SRC_SEL_MASK;
848      radeon_outpll( mmio, PIXCLKS_CNTL, tmp | PIX2CLK_SRC_SEL_P2PLLCLK );
849 
850      radeon_out32( mmio, CRTC2_GEN_CNTL, rcrtc2->regs.rCRTC2_GEN_CNTL );
851 
852      dfb_gfxcard_unlock();
853 }
854 
855 static inline u8
calc_gamma(float n,float d)856 calc_gamma( float n, float d )
857 {
858      int ret;
859 
860      ret = 255.0 * n / d + 0.5;
861      if (ret > 255)
862           ret = 255;
863      else if (ret < 0)
864           ret = 0;
865 
866      return ret;
867 }
868 
869 static void
crtc2_calc_palette(RadeonDriverData * rdrv,RadeonCrtc2LayerData * rcrtc2,CoreLayerRegionConfig * config,DFBColorAdjustment * adjustment,CorePalette * palette)870 crtc2_calc_palette( RadeonDriverData      *rdrv,
871                     RadeonCrtc2LayerData  *rcrtc2,
872                     CoreLayerRegionConfig *config,
873                     DFBColorAdjustment    *adjustment,
874                     CorePalette           *palette )
875 {
876      unsigned int i;
877      int          r, g, b;
878 
879      switch (config->format) {
880           case DSPF_LUT8:
881                rcrtc2->lut.size = MAX( palette->num_entries, 256 );
882                for (i = 0; i < rcrtc2->lut.size; i++) {
883                     rcrtc2->lut.r[i] = palette->entries[i].r;
884                     rcrtc2->lut.g[i] = palette->entries[i].g;
885                     rcrtc2->lut.b[i] = palette->entries[i].b;
886                }
887                break;
888           case DSPF_RGB332:
889                rcrtc2->lut.size = 256;
890                for (i = 0, r = 0; r < 8; r++) {
891                     for (g = 0; g < 8; g++) {
892                          for (b = 0; b < 4; b++) {
893                               rcrtc2->lut.r[i] = calc_gamma( r, 7 );
894                               rcrtc2->lut.g[i] = calc_gamma( g, 7 );
895                               rcrtc2->lut.b[i] = calc_gamma( b, 3 );
896                               i++;
897                          }
898                     }
899                }
900                break;
901           case DSPF_RGB555:
902           case DSPF_ARGB1555:
903                rcrtc2->lut.size = 32;
904                for (i = 0; i < 32; i++) {
905                     rcrtc2->lut.r[i] =
906                     rcrtc2->lut.g[i] =
907                     rcrtc2->lut.b[i] = calc_gamma( i, 31 );
908                }
909                break;
910           case DSPF_RGB16:
911                rcrtc2->lut.size = 64;
912                for (i = 0; i < 64; i++) {
913                     rcrtc2->lut.r[i] =
914                     rcrtc2->lut.b[i] = calc_gamma( i/2, 31 );
915                     rcrtc2->lut.g[i] = calc_gamma( i, 63 );
916                }
917                break;
918           default:
919                rcrtc2->lut.size = 256;
920                for (i = 0; i < 256; i++) {
921                     rcrtc2->lut.r[i] =
922                     rcrtc2->lut.b[i] =
923                     rcrtc2->lut.g[i] = i;
924                }
925                break;
926      }
927 
928      if (adjustment->flags & DCAF_BRIGHTNESS) {
929           int brightness = (adjustment->brightness >> 8) - 128;
930 
931           for (i = 0; i < rcrtc2->lut.size; i++) {
932                r = rcrtc2->lut.r[i] + brightness;
933                g = rcrtc2->lut.g[i] + brightness;
934                b = rcrtc2->lut.b[i] + brightness;
935                rcrtc2->lut.r[i] = CLAMP( r, 0, 255 );
936                rcrtc2->lut.g[i] = CLAMP( g, 0, 255 );
937                rcrtc2->lut.b[i] = CLAMP( b, 0, 255 );
938           }
939      }
940 
941      if (adjustment->flags & DCAF_CONTRAST) {
942           int contrast = adjustment->contrast;
943 
944           for (i = 0; i < rcrtc2->lut.size; i++) {
945                r = rcrtc2->lut.r[i] * contrast / 0x8000;
946                g = rcrtc2->lut.g[i] * contrast / 0x8000;
947                b = rcrtc2->lut.b[i] * contrast / 0x8000;
948                rcrtc2->lut.r[i] = CLAMP( r, 0, 255 );
949                rcrtc2->lut.g[i] = CLAMP( g, 0, 255 );
950                rcrtc2->lut.b[i] = CLAMP( b, 0, 255 );
951           }
952      }
953 
954      if (adjustment->flags & DCAF_SATURATION) {
955           int saturation = adjustment->saturation >> 8;
956 
957           for (i = 0; i < rcrtc2->lut.size; i++) {
958                if (saturation > 128) {
959                     float gray  = ((float)saturation - 128.0)/128.0;
960                     float color = 1.0 - gray;
961 
962                     r = (((float)rcrtc2->lut.r[i] - 128.0 * gray)/color);
963                     g = (((float)rcrtc2->lut.g[i] - 128.0 * gray)/color);
964                     b = (((float)rcrtc2->lut.b[i] - 128.0 * gray)/color);
965                }
966                else {
967                     float color = (float)saturation/128.0;
968                     float gray  = 1.0 - color;
969 
970                     r = (((float)rcrtc2->lut.r[i] * color) + (128.0 * gray));
971                     g = (((float)rcrtc2->lut.g[i] * color) + (128.0 * gray));
972                     b = (((float)rcrtc2->lut.b[i] * color) + (128.0 * gray));
973                }
974                rcrtc2->lut.r[i] = CLAMP( r, 0, 255 );
975                rcrtc2->lut.g[i] = CLAMP( g, 0, 255 );
976                rcrtc2->lut.b[i] = CLAMP( b, 0, 255 );
977           }
978      }
979 }
980 
981 static void
crtc2_set_palette(RadeonDriverData * rdrv,RadeonCrtc2LayerData * rcrtc2)982 crtc2_set_palette( RadeonDriverData     *rdrv,
983                    RadeonCrtc2LayerData *rcrtc2 )
984 {
985      volatile u8 *mmio = rdrv->mmio_base;
986      u32          tmp;
987      int          i, j;
988 
989      if (!rcrtc2->lut.size) {
990           D_WARN( "palette is empty" );
991           return;
992      }
993 
994      dfb_gfxcard_lock( GDLF_WAIT | GDLF_SYNC );
995 
996      tmp = radeon_in32( mmio, DAC_CNTL2 );
997      radeon_out32( mmio, DAC_CNTL2, tmp | DAC2_PALETTE_ACC_CTL );
998 
999      j = 256 / rcrtc2->lut.size;
1000      for (i = 0; i < rcrtc2->lut.size; i++) {
1001           radeon_out32( mmio, PALETTE_INDEX, i*j );
1002           radeon_out32( mmio, PALETTE_DATA, (rcrtc2->lut.b[i]      ) |
1003                                             (rcrtc2->lut.g[i] <<  8) |
1004                                             (rcrtc2->lut.r[i] << 16) );
1005      }
1006 
1007      radeon_out32( mmio, DAC_CNTL2, tmp );
1008 
1009      dfb_gfxcard_unlock();
1010 }
1011 
1012