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