drm/fb: add setcmap and fix 8-bit support.
[safe/jmp/linux-2.6] / drivers / gpu / drm / radeon / atombios_crtc.c
1 /*
2  * Copyright 2007-8 Advanced Micro Devices, Inc.
3  * Copyright 2008 Red Hat Inc.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included in
13  * all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
19  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21  * OTHER DEALINGS IN THE SOFTWARE.
22  *
23  * Authors: Dave Airlie
24  *          Alex Deucher
25  */
26 #include <drm/drmP.h>
27 #include <drm/drm_crtc_helper.h>
28 #include <drm/radeon_drm.h>
29 #include "radeon_fixed.h"
30 #include "radeon.h"
31 #include "atom.h"
32 #include "atom-bits.h"
33
34 /* evil but including atombios.h is much worse */
35 bool radeon_atom_get_tv_timings(struct radeon_device *rdev, int index,
36                                 SET_CRTC_TIMING_PARAMETERS_PS_ALLOCATION *crtc_timing,
37                                 int32_t *pixel_clock);
38 static void atombios_overscan_setup(struct drm_crtc *crtc,
39                                     struct drm_display_mode *mode,
40                                     struct drm_display_mode *adjusted_mode)
41 {
42         struct drm_device *dev = crtc->dev;
43         struct radeon_device *rdev = dev->dev_private;
44         struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
45         SET_CRTC_OVERSCAN_PS_ALLOCATION args;
46         int index = GetIndexIntoMasterTable(COMMAND, SetCRTC_OverScan);
47         int a1, a2;
48
49         memset(&args, 0, sizeof(args));
50
51         args.usOverscanRight = 0;
52         args.usOverscanLeft = 0;
53         args.usOverscanBottom = 0;
54         args.usOverscanTop = 0;
55         args.ucCRTC = radeon_crtc->crtc_id;
56
57         switch (radeon_crtc->rmx_type) {
58         case RMX_CENTER:
59                 args.usOverscanTop = (adjusted_mode->crtc_vdisplay - mode->crtc_vdisplay) / 2;
60                 args.usOverscanBottom = (adjusted_mode->crtc_vdisplay - mode->crtc_vdisplay) / 2;
61                 args.usOverscanLeft = (adjusted_mode->crtc_hdisplay - mode->crtc_hdisplay) / 2;
62                 args.usOverscanRight = (adjusted_mode->crtc_hdisplay - mode->crtc_hdisplay) / 2;
63                 atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
64                 break;
65         case RMX_ASPECT:
66                 a1 = mode->crtc_vdisplay * adjusted_mode->crtc_hdisplay;
67                 a2 = adjusted_mode->crtc_vdisplay * mode->crtc_hdisplay;
68
69                 if (a1 > a2) {
70                         args.usOverscanLeft = (adjusted_mode->crtc_hdisplay - (a2 / mode->crtc_vdisplay)) / 2;
71                         args.usOverscanRight = (adjusted_mode->crtc_hdisplay - (a2 / mode->crtc_vdisplay)) / 2;
72                 } else if (a2 > a1) {
73                         args.usOverscanLeft = (adjusted_mode->crtc_vdisplay - (a1 / mode->crtc_hdisplay)) / 2;
74                         args.usOverscanRight = (adjusted_mode->crtc_vdisplay - (a1 / mode->crtc_hdisplay)) / 2;
75                 }
76                 atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
77                 break;
78         case RMX_FULL:
79         default:
80                 args.usOverscanRight = 0;
81                 args.usOverscanLeft = 0;
82                 args.usOverscanBottom = 0;
83                 args.usOverscanTop = 0;
84                 atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
85                 break;
86         }
87 }
88
89 static void atombios_scaler_setup(struct drm_crtc *crtc)
90 {
91         struct drm_device *dev = crtc->dev;
92         struct radeon_device *rdev = dev->dev_private;
93         struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
94         ENABLE_SCALER_PS_ALLOCATION args;
95         int index = GetIndexIntoMasterTable(COMMAND, EnableScaler);
96
97         /* fixme - fill in enc_priv for atom dac */
98         enum radeon_tv_std tv_std = TV_STD_NTSC;
99         bool is_tv = false, is_cv = false;
100         struct drm_encoder *encoder;
101
102         if (!ASIC_IS_AVIVO(rdev) && radeon_crtc->crtc_id)
103                 return;
104
105         list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
106                 /* find tv std */
107                 if (encoder->crtc == crtc) {
108                         struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
109                         if (radeon_encoder->active_device & ATOM_DEVICE_TV_SUPPORT) {
110                                 struct radeon_encoder_atom_dac *tv_dac = radeon_encoder->enc_priv;
111                                 tv_std = tv_dac->tv_std;
112                                 is_tv = true;
113                         }
114                 }
115         }
116
117         memset(&args, 0, sizeof(args));
118
119         args.ucScaler = radeon_crtc->crtc_id;
120
121         if (is_tv) {
122                 switch (tv_std) {
123                 case TV_STD_NTSC:
124                 default:
125                         args.ucTVStandard = ATOM_TV_NTSC;
126                         break;
127                 case TV_STD_PAL:
128                         args.ucTVStandard = ATOM_TV_PAL;
129                         break;
130                 case TV_STD_PAL_M:
131                         args.ucTVStandard = ATOM_TV_PALM;
132                         break;
133                 case TV_STD_PAL_60:
134                         args.ucTVStandard = ATOM_TV_PAL60;
135                         break;
136                 case TV_STD_NTSC_J:
137                         args.ucTVStandard = ATOM_TV_NTSCJ;
138                         break;
139                 case TV_STD_SCART_PAL:
140                         args.ucTVStandard = ATOM_TV_PAL; /* ??? */
141                         break;
142                 case TV_STD_SECAM:
143                         args.ucTVStandard = ATOM_TV_SECAM;
144                         break;
145                 case TV_STD_PAL_CN:
146                         args.ucTVStandard = ATOM_TV_PALCN;
147                         break;
148                 }
149                 args.ucEnable = SCALER_ENABLE_MULTITAP_MODE;
150         } else if (is_cv) {
151                 args.ucTVStandard = ATOM_TV_CV;
152                 args.ucEnable = SCALER_ENABLE_MULTITAP_MODE;
153         } else {
154                 switch (radeon_crtc->rmx_type) {
155                 case RMX_FULL:
156                         args.ucEnable = ATOM_SCALER_EXPANSION;
157                         break;
158                 case RMX_CENTER:
159                         args.ucEnable = ATOM_SCALER_CENTER;
160                         break;
161                 case RMX_ASPECT:
162                         args.ucEnable = ATOM_SCALER_EXPANSION;
163                         break;
164                 default:
165                         if (ASIC_IS_AVIVO(rdev))
166                                 args.ucEnable = ATOM_SCALER_DISABLE;
167                         else
168                                 args.ucEnable = ATOM_SCALER_CENTER;
169                         break;
170                 }
171         }
172         atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
173         if ((is_tv || is_cv)
174             && rdev->family >= CHIP_RV515 && rdev->family <= CHIP_R580) {
175                 atom_rv515_force_tv_scaler(rdev, radeon_crtc);
176         }
177 }
178
179 static void atombios_lock_crtc(struct drm_crtc *crtc, int lock)
180 {
181         struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
182         struct drm_device *dev = crtc->dev;
183         struct radeon_device *rdev = dev->dev_private;
184         int index =
185             GetIndexIntoMasterTable(COMMAND, UpdateCRTC_DoubleBufferRegisters);
186         ENABLE_CRTC_PS_ALLOCATION args;
187
188         memset(&args, 0, sizeof(args));
189
190         args.ucCRTC = radeon_crtc->crtc_id;
191         args.ucEnable = lock;
192
193         atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
194 }
195
196 static void atombios_enable_crtc(struct drm_crtc *crtc, int state)
197 {
198         struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
199         struct drm_device *dev = crtc->dev;
200         struct radeon_device *rdev = dev->dev_private;
201         int index = GetIndexIntoMasterTable(COMMAND, EnableCRTC);
202         ENABLE_CRTC_PS_ALLOCATION args;
203
204         memset(&args, 0, sizeof(args));
205
206         args.ucCRTC = radeon_crtc->crtc_id;
207         args.ucEnable = state;
208
209         atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
210 }
211
212 static void atombios_enable_crtc_memreq(struct drm_crtc *crtc, int state)
213 {
214         struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
215         struct drm_device *dev = crtc->dev;
216         struct radeon_device *rdev = dev->dev_private;
217         int index = GetIndexIntoMasterTable(COMMAND, EnableCRTCMemReq);
218         ENABLE_CRTC_PS_ALLOCATION args;
219
220         memset(&args, 0, sizeof(args));
221
222         args.ucCRTC = radeon_crtc->crtc_id;
223         args.ucEnable = state;
224
225         atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
226 }
227
228 static void atombios_blank_crtc(struct drm_crtc *crtc, int state)
229 {
230         struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
231         struct drm_device *dev = crtc->dev;
232         struct radeon_device *rdev = dev->dev_private;
233         int index = GetIndexIntoMasterTable(COMMAND, BlankCRTC);
234         BLANK_CRTC_PS_ALLOCATION args;
235
236         memset(&args, 0, sizeof(args));
237
238         args.ucCRTC = radeon_crtc->crtc_id;
239         args.ucBlanking = state;
240
241         atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
242 }
243
244 void atombios_crtc_dpms(struct drm_crtc *crtc, int mode)
245 {
246         struct drm_device *dev = crtc->dev;
247         struct radeon_device *rdev = dev->dev_private;
248
249         switch (mode) {
250         case DRM_MODE_DPMS_ON:
251                 if (ASIC_IS_DCE3(rdev))
252                         atombios_enable_crtc_memreq(crtc, 1);
253                 atombios_enable_crtc(crtc, 1);
254                 atombios_blank_crtc(crtc, 0);
255                 break;
256         case DRM_MODE_DPMS_STANDBY:
257         case DRM_MODE_DPMS_SUSPEND:
258         case DRM_MODE_DPMS_OFF:
259                 atombios_blank_crtc(crtc, 1);
260                 atombios_enable_crtc(crtc, 0);
261                 if (ASIC_IS_DCE3(rdev))
262                         atombios_enable_crtc_memreq(crtc, 0);
263                 break;
264         }
265
266         if (mode != DRM_MODE_DPMS_OFF) {
267                 radeon_crtc_load_lut(crtc);
268         }
269 }
270
271 static void
272 atombios_set_crtc_dtd_timing(struct drm_crtc *crtc,
273                              SET_CRTC_USING_DTD_TIMING_PARAMETERS * crtc_param)
274 {
275         struct drm_device *dev = crtc->dev;
276         struct radeon_device *rdev = dev->dev_private;
277         SET_CRTC_USING_DTD_TIMING_PARAMETERS conv_param;
278         int index = GetIndexIntoMasterTable(COMMAND, SetCRTC_UsingDTDTiming);
279
280         conv_param.usH_Size = cpu_to_le16(crtc_param->usH_Size);
281         conv_param.usH_Blanking_Time =
282             cpu_to_le16(crtc_param->usH_Blanking_Time);
283         conv_param.usV_Size = cpu_to_le16(crtc_param->usV_Size);
284         conv_param.usV_Blanking_Time =
285             cpu_to_le16(crtc_param->usV_Blanking_Time);
286         conv_param.usH_SyncOffset = cpu_to_le16(crtc_param->usH_SyncOffset);
287         conv_param.usH_SyncWidth = cpu_to_le16(crtc_param->usH_SyncWidth);
288         conv_param.usV_SyncOffset = cpu_to_le16(crtc_param->usV_SyncOffset);
289         conv_param.usV_SyncWidth = cpu_to_le16(crtc_param->usV_SyncWidth);
290         conv_param.susModeMiscInfo.usAccess =
291             cpu_to_le16(crtc_param->susModeMiscInfo.usAccess);
292         conv_param.ucCRTC = crtc_param->ucCRTC;
293
294         printk("executing set crtc dtd timing\n");
295         atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&conv_param);
296 }
297
298 void atombios_crtc_set_timing(struct drm_crtc *crtc,
299                               SET_CRTC_TIMING_PARAMETERS_PS_ALLOCATION *
300                               crtc_param)
301 {
302         struct drm_device *dev = crtc->dev;
303         struct radeon_device *rdev = dev->dev_private;
304         SET_CRTC_TIMING_PARAMETERS_PS_ALLOCATION conv_param;
305         int index = GetIndexIntoMasterTable(COMMAND, SetCRTC_Timing);
306
307         conv_param.usH_Total = cpu_to_le16(crtc_param->usH_Total);
308         conv_param.usH_Disp = cpu_to_le16(crtc_param->usH_Disp);
309         conv_param.usH_SyncStart = cpu_to_le16(crtc_param->usH_SyncStart);
310         conv_param.usH_SyncWidth = cpu_to_le16(crtc_param->usH_SyncWidth);
311         conv_param.usV_Total = cpu_to_le16(crtc_param->usV_Total);
312         conv_param.usV_Disp = cpu_to_le16(crtc_param->usV_Disp);
313         conv_param.usV_SyncStart = cpu_to_le16(crtc_param->usV_SyncStart);
314         conv_param.usV_SyncWidth = cpu_to_le16(crtc_param->usV_SyncWidth);
315         conv_param.susModeMiscInfo.usAccess =
316             cpu_to_le16(crtc_param->susModeMiscInfo.usAccess);
317         conv_param.ucCRTC = crtc_param->ucCRTC;
318         conv_param.ucOverscanRight = crtc_param->ucOverscanRight;
319         conv_param.ucOverscanLeft = crtc_param->ucOverscanLeft;
320         conv_param.ucOverscanBottom = crtc_param->ucOverscanBottom;
321         conv_param.ucOverscanTop = crtc_param->ucOverscanTop;
322         conv_param.ucReserved = crtc_param->ucReserved;
323
324         printk("executing set crtc timing\n");
325         atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&conv_param);
326 }
327
328 void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode)
329 {
330         struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
331         struct drm_device *dev = crtc->dev;
332         struct radeon_device *rdev = dev->dev_private;
333         struct drm_encoder *encoder = NULL;
334         struct radeon_encoder *radeon_encoder = NULL;
335         uint8_t frev, crev;
336         int index = GetIndexIntoMasterTable(COMMAND, SetPixelClock);
337         SET_PIXEL_CLOCK_PS_ALLOCATION args;
338         PIXEL_CLOCK_PARAMETERS *spc1_ptr;
339         PIXEL_CLOCK_PARAMETERS_V2 *spc2_ptr;
340         PIXEL_CLOCK_PARAMETERS_V3 *spc3_ptr;
341         uint32_t sclock = mode->clock;
342         uint32_t ref_div = 0, fb_div = 0, frac_fb_div = 0, post_div = 0;
343         struct radeon_pll *pll;
344         int pll_flags = 0;
345
346         memset(&args, 0, sizeof(args));
347
348         if (ASIC_IS_AVIVO(rdev)) {
349                 uint32_t ss_cntl;
350
351                 if ((rdev->family == CHIP_RS600) ||
352                     (rdev->family == CHIP_RS690) ||
353                     (rdev->family == CHIP_RS740))
354                         pll_flags |= (RADEON_PLL_USE_FRAC_FB_DIV |
355                                       RADEON_PLL_PREFER_CLOSEST_LOWER);
356
357                 if (ASIC_IS_DCE32(rdev) && mode->clock > 200000)        /* range limits??? */
358                         pll_flags |= RADEON_PLL_PREFER_HIGH_FB_DIV;
359                 else
360                         pll_flags |= RADEON_PLL_PREFER_LOW_REF_DIV;
361
362                 /* disable spread spectrum clocking for now -- thanks Hedy Lamarr */
363                 if (radeon_crtc->crtc_id == 0) {
364                         ss_cntl = RREG32(AVIVO_P1PLL_INT_SS_CNTL);
365                         WREG32(AVIVO_P1PLL_INT_SS_CNTL, ss_cntl & ~1);
366                 } else {
367                         ss_cntl = RREG32(AVIVO_P2PLL_INT_SS_CNTL);
368                         WREG32(AVIVO_P2PLL_INT_SS_CNTL, ss_cntl & ~1);
369                 }
370         } else {
371                 pll_flags |= RADEON_PLL_LEGACY;
372
373                 if (mode->clock > 200000)       /* range limits??? */
374                         pll_flags |= RADEON_PLL_PREFER_HIGH_FB_DIV;
375                 else
376                         pll_flags |= RADEON_PLL_PREFER_LOW_REF_DIV;
377
378         }
379
380         list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
381                 if (encoder->crtc == crtc) {
382                         if (!ASIC_IS_AVIVO(rdev)) {
383                                 if (encoder->encoder_type !=
384                                     DRM_MODE_ENCODER_DAC)
385                                         pll_flags |= RADEON_PLL_NO_ODD_POST_DIV;
386                                 if (!ASIC_IS_AVIVO(rdev)
387                                     && (encoder->encoder_type ==
388                                         DRM_MODE_ENCODER_LVDS))
389                                         pll_flags |= RADEON_PLL_USE_REF_DIV;
390                         }
391                         radeon_encoder = to_radeon_encoder(encoder);
392                         break;
393                 }
394         }
395
396         if (radeon_crtc->crtc_id == 0)
397                 pll = &rdev->clock.p1pll;
398         else
399                 pll = &rdev->clock.p2pll;
400
401         radeon_compute_pll(pll, mode->clock, &sclock, &fb_div, &frac_fb_div,
402                            &ref_div, &post_div, pll_flags);
403
404         atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev,
405                               &crev);
406
407         switch (frev) {
408         case 1:
409                 switch (crev) {
410                 case 1:
411                         spc1_ptr = (PIXEL_CLOCK_PARAMETERS *) & args.sPCLKInput;
412                         spc1_ptr->usPixelClock = cpu_to_le16(sclock);
413                         spc1_ptr->usRefDiv = cpu_to_le16(ref_div);
414                         spc1_ptr->usFbDiv = cpu_to_le16(fb_div);
415                         spc1_ptr->ucFracFbDiv = frac_fb_div;
416                         spc1_ptr->ucPostDiv = post_div;
417                         spc1_ptr->ucPpll =
418                             radeon_crtc->crtc_id ? ATOM_PPLL2 : ATOM_PPLL1;
419                         spc1_ptr->ucCRTC = radeon_crtc->crtc_id;
420                         spc1_ptr->ucRefDivSrc = 1;
421                         break;
422                 case 2:
423                         spc2_ptr =
424                             (PIXEL_CLOCK_PARAMETERS_V2 *) & args.sPCLKInput;
425                         spc2_ptr->usPixelClock = cpu_to_le16(sclock);
426                         spc2_ptr->usRefDiv = cpu_to_le16(ref_div);
427                         spc2_ptr->usFbDiv = cpu_to_le16(fb_div);
428                         spc2_ptr->ucFracFbDiv = frac_fb_div;
429                         spc2_ptr->ucPostDiv = post_div;
430                         spc2_ptr->ucPpll =
431                             radeon_crtc->crtc_id ? ATOM_PPLL2 : ATOM_PPLL1;
432                         spc2_ptr->ucCRTC = radeon_crtc->crtc_id;
433                         spc2_ptr->ucRefDivSrc = 1;
434                         break;
435                 case 3:
436                         if (!encoder)
437                                 return;
438                         spc3_ptr =
439                             (PIXEL_CLOCK_PARAMETERS_V3 *) & args.sPCLKInput;
440                         spc3_ptr->usPixelClock = cpu_to_le16(sclock);
441                         spc3_ptr->usRefDiv = cpu_to_le16(ref_div);
442                         spc3_ptr->usFbDiv = cpu_to_le16(fb_div);
443                         spc3_ptr->ucFracFbDiv = frac_fb_div;
444                         spc3_ptr->ucPostDiv = post_div;
445                         spc3_ptr->ucPpll =
446                             radeon_crtc->crtc_id ? ATOM_PPLL2 : ATOM_PPLL1;
447                         spc3_ptr->ucMiscInfo = (radeon_crtc->crtc_id << 2);
448                         spc3_ptr->ucTransmitterId = radeon_encoder->encoder_id;
449                         spc3_ptr->ucEncoderMode =
450                             atombios_get_encoder_mode(encoder);
451                         break;
452                 default:
453                         DRM_ERROR("Unknown table version %d %d\n", frev, crev);
454                         return;
455                 }
456                 break;
457         default:
458                 DRM_ERROR("Unknown table version %d %d\n", frev, crev);
459                 return;
460         }
461
462         printk("executing set pll\n");
463         atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
464 }
465
466 int atombios_crtc_set_base(struct drm_crtc *crtc, int x, int y,
467                            struct drm_framebuffer *old_fb)
468 {
469         struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
470         struct drm_device *dev = crtc->dev;
471         struct radeon_device *rdev = dev->dev_private;
472         struct radeon_framebuffer *radeon_fb;
473         struct drm_gem_object *obj;
474         struct drm_radeon_gem_object *obj_priv;
475         uint64_t fb_location;
476         uint32_t fb_format, fb_pitch_pixels, tiling_flags;
477
478         if (!crtc->fb)
479                 return -EINVAL;
480
481         radeon_fb = to_radeon_framebuffer(crtc->fb);
482
483         obj = radeon_fb->obj;
484         obj_priv = obj->driver_private;
485
486         if (radeon_gem_object_pin(obj, RADEON_GEM_DOMAIN_VRAM, &fb_location)) {
487                 return -EINVAL;
488         }
489
490         switch (crtc->fb->bits_per_pixel) {
491         case 8:
492                 fb_format =
493                     AVIVO_D1GRPH_CONTROL_DEPTH_8BPP |
494                     AVIVO_D1GRPH_CONTROL_8BPP_INDEXED;
495                 break;
496         case 15:
497                 fb_format =
498                     AVIVO_D1GRPH_CONTROL_DEPTH_16BPP |
499                     AVIVO_D1GRPH_CONTROL_16BPP_ARGB1555;
500                 break;
501         case 16:
502                 fb_format =
503                     AVIVO_D1GRPH_CONTROL_DEPTH_16BPP |
504                     AVIVO_D1GRPH_CONTROL_16BPP_RGB565;
505                 break;
506         case 24:
507         case 32:
508                 fb_format =
509                     AVIVO_D1GRPH_CONTROL_DEPTH_32BPP |
510                     AVIVO_D1GRPH_CONTROL_32BPP_ARGB8888;
511                 break;
512         default:
513                 DRM_ERROR("Unsupported screen depth %d\n",
514                           crtc->fb->bits_per_pixel);
515                 return -EINVAL;
516         }
517
518         radeon_object_get_tiling_flags(obj->driver_private,
519                                        &tiling_flags, NULL);
520         if (tiling_flags & RADEON_TILING_MACRO)
521                 fb_format |= AVIVO_D1GRPH_MACRO_ADDRESS_MODE;
522
523         if (tiling_flags & RADEON_TILING_MICRO)
524                 fb_format |= AVIVO_D1GRPH_TILED;
525
526         if (radeon_crtc->crtc_id == 0)
527                 WREG32(AVIVO_D1VGA_CONTROL, 0);
528         else
529                 WREG32(AVIVO_D2VGA_CONTROL, 0);
530         WREG32(AVIVO_D1GRPH_PRIMARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset,
531                (u32) fb_location);
532         WREG32(AVIVO_D1GRPH_SECONDARY_SURFACE_ADDRESS +
533                radeon_crtc->crtc_offset, (u32) fb_location);
534         WREG32(AVIVO_D1GRPH_CONTROL + radeon_crtc->crtc_offset, fb_format);
535
536         WREG32(AVIVO_D1GRPH_SURFACE_OFFSET_X + radeon_crtc->crtc_offset, 0);
537         WREG32(AVIVO_D1GRPH_SURFACE_OFFSET_Y + radeon_crtc->crtc_offset, 0);
538         WREG32(AVIVO_D1GRPH_X_START + radeon_crtc->crtc_offset, 0);
539         WREG32(AVIVO_D1GRPH_Y_START + radeon_crtc->crtc_offset, 0);
540         WREG32(AVIVO_D1GRPH_X_END + radeon_crtc->crtc_offset, crtc->fb->width);
541         WREG32(AVIVO_D1GRPH_Y_END + radeon_crtc->crtc_offset, crtc->fb->height);
542
543         fb_pitch_pixels = crtc->fb->pitch / (crtc->fb->bits_per_pixel / 8);
544         WREG32(AVIVO_D1GRPH_PITCH + radeon_crtc->crtc_offset, fb_pitch_pixels);
545         WREG32(AVIVO_D1GRPH_ENABLE + radeon_crtc->crtc_offset, 1);
546
547         WREG32(AVIVO_D1MODE_DESKTOP_HEIGHT + radeon_crtc->crtc_offset,
548                crtc->mode.vdisplay);
549         x &= ~3;
550         y &= ~1;
551         WREG32(AVIVO_D1MODE_VIEWPORT_START + radeon_crtc->crtc_offset,
552                (x << 16) | y);
553         WREG32(AVIVO_D1MODE_VIEWPORT_SIZE + radeon_crtc->crtc_offset,
554                (crtc->mode.hdisplay << 16) | crtc->mode.vdisplay);
555
556         if (crtc->mode.flags & DRM_MODE_FLAG_INTERLACE)
557                 WREG32(AVIVO_D1MODE_DATA_FORMAT + radeon_crtc->crtc_offset,
558                        AVIVO_D1MODE_INTERLEAVE_EN);
559         else
560                 WREG32(AVIVO_D1MODE_DATA_FORMAT + radeon_crtc->crtc_offset, 0);
561
562         if (old_fb && old_fb != crtc->fb) {
563                 radeon_fb = to_radeon_framebuffer(old_fb);
564                 radeon_gem_object_unpin(radeon_fb->obj);
565         }
566         return 0;
567 }
568
569 int atombios_crtc_mode_set(struct drm_crtc *crtc,
570                            struct drm_display_mode *mode,
571                            struct drm_display_mode *adjusted_mode,
572                            int x, int y, struct drm_framebuffer *old_fb)
573 {
574         struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
575         struct drm_device *dev = crtc->dev;
576         struct radeon_device *rdev = dev->dev_private;
577         struct drm_encoder *encoder;
578         SET_CRTC_TIMING_PARAMETERS_PS_ALLOCATION crtc_timing;
579         int need_tv_timings = 0;
580         bool ret;
581
582         /* TODO color tiling */
583         memset(&crtc_timing, 0, sizeof(crtc_timing));
584
585         list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
586                 /* find tv std */
587                 if (encoder->crtc == crtc) {
588                         struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
589
590                         if (radeon_encoder->active_device & ATOM_DEVICE_TV_SUPPORT) {
591                                 struct radeon_encoder_atom_dac *tv_dac = radeon_encoder->enc_priv;
592                                 if (tv_dac) {
593                                         if (tv_dac->tv_std == TV_STD_NTSC ||
594                                             tv_dac->tv_std == TV_STD_NTSC_J ||
595                                             tv_dac->tv_std == TV_STD_PAL_M)
596                                                 need_tv_timings = 1;
597                                         else
598                                                 need_tv_timings = 2;
599                                         break;
600                                 }
601                         }
602                 }
603         }
604
605         crtc_timing.ucCRTC = radeon_crtc->crtc_id;
606         if (need_tv_timings) {
607                 ret = radeon_atom_get_tv_timings(rdev, need_tv_timings - 1,
608                                                  &crtc_timing, &adjusted_mode->clock);
609                 if (ret == false)
610                         need_tv_timings = 0;
611         }
612
613         if (!need_tv_timings) {
614                 crtc_timing.usH_Total = adjusted_mode->crtc_htotal;
615                 crtc_timing.usH_Disp = adjusted_mode->crtc_hdisplay;
616                 crtc_timing.usH_SyncStart = adjusted_mode->crtc_hsync_start;
617                 crtc_timing.usH_SyncWidth =
618                         adjusted_mode->crtc_hsync_end - adjusted_mode->crtc_hsync_start;
619
620                 crtc_timing.usV_Total = adjusted_mode->crtc_vtotal;
621                 crtc_timing.usV_Disp = adjusted_mode->crtc_vdisplay;
622                 crtc_timing.usV_SyncStart = adjusted_mode->crtc_vsync_start;
623                 crtc_timing.usV_SyncWidth =
624                         adjusted_mode->crtc_vsync_end - adjusted_mode->crtc_vsync_start;
625
626                 if (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC)
627                         crtc_timing.susModeMiscInfo.usAccess |= ATOM_VSYNC_POLARITY;
628
629                 if (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC)
630                         crtc_timing.susModeMiscInfo.usAccess |= ATOM_HSYNC_POLARITY;
631
632                 if (adjusted_mode->flags & DRM_MODE_FLAG_CSYNC)
633                         crtc_timing.susModeMiscInfo.usAccess |= ATOM_COMPOSITESYNC;
634
635                 if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE)
636                         crtc_timing.susModeMiscInfo.usAccess |= ATOM_INTERLACE;
637
638                 if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
639                         crtc_timing.susModeMiscInfo.usAccess |= ATOM_DOUBLE_CLOCK_MODE;
640         }
641
642         atombios_crtc_set_pll(crtc, adjusted_mode);
643         atombios_crtc_set_timing(crtc, &crtc_timing);
644
645         if (ASIC_IS_AVIVO(rdev))
646                 atombios_crtc_set_base(crtc, x, y, old_fb);
647         else {
648                 if (radeon_crtc->crtc_id == 0) {
649                         SET_CRTC_USING_DTD_TIMING_PARAMETERS crtc_dtd_timing;
650                         memset(&crtc_dtd_timing, 0, sizeof(crtc_dtd_timing));
651
652                         /* setup FP shadow regs on R4xx */
653                         crtc_dtd_timing.ucCRTC = radeon_crtc->crtc_id;
654                         crtc_dtd_timing.usH_Size = adjusted_mode->crtc_hdisplay;
655                         crtc_dtd_timing.usV_Size = adjusted_mode->crtc_vdisplay;
656                         crtc_dtd_timing.usH_Blanking_Time =
657                             adjusted_mode->crtc_hblank_end -
658                             adjusted_mode->crtc_hdisplay;
659                         crtc_dtd_timing.usV_Blanking_Time =
660                             adjusted_mode->crtc_vblank_end -
661                             adjusted_mode->crtc_vdisplay;
662                         crtc_dtd_timing.usH_SyncOffset =
663                             adjusted_mode->crtc_hsync_start -
664                             adjusted_mode->crtc_hdisplay;
665                         crtc_dtd_timing.usV_SyncOffset =
666                             adjusted_mode->crtc_vsync_start -
667                             adjusted_mode->crtc_vdisplay;
668                         crtc_dtd_timing.usH_SyncWidth =
669                             adjusted_mode->crtc_hsync_end -
670                             adjusted_mode->crtc_hsync_start;
671                         crtc_dtd_timing.usV_SyncWidth =
672                             adjusted_mode->crtc_vsync_end -
673                             adjusted_mode->crtc_vsync_start;
674                         /* crtc_dtd_timing.ucH_Border = adjusted_mode->crtc_hborder; */
675                         /* crtc_dtd_timing.ucV_Border = adjusted_mode->crtc_vborder; */
676
677                         if (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC)
678                                 crtc_dtd_timing.susModeMiscInfo.usAccess |=
679                                     ATOM_VSYNC_POLARITY;
680
681                         if (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC)
682                                 crtc_dtd_timing.susModeMiscInfo.usAccess |=
683                                     ATOM_HSYNC_POLARITY;
684
685                         if (adjusted_mode->flags & DRM_MODE_FLAG_CSYNC)
686                                 crtc_dtd_timing.susModeMiscInfo.usAccess |=
687                                     ATOM_COMPOSITESYNC;
688
689                         if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE)
690                                 crtc_dtd_timing.susModeMiscInfo.usAccess |=
691                                     ATOM_INTERLACE;
692
693                         if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
694                                 crtc_dtd_timing.susModeMiscInfo.usAccess |=
695                                     ATOM_DOUBLE_CLOCK_MODE;
696
697                         atombios_set_crtc_dtd_timing(crtc, &crtc_dtd_timing);
698                 }
699                 radeon_crtc_set_base(crtc, x, y, old_fb);
700                 radeon_legacy_atom_set_surface(crtc);
701         }
702         atombios_overscan_setup(crtc, mode, adjusted_mode);
703         atombios_scaler_setup(crtc);
704         radeon_bandwidth_update(rdev);
705         return 0;
706 }
707
708 static bool atombios_crtc_mode_fixup(struct drm_crtc *crtc,
709                                      struct drm_display_mode *mode,
710                                      struct drm_display_mode *adjusted_mode)
711 {
712         if (!radeon_crtc_scaling_mode_fixup(crtc, mode, adjusted_mode))
713                 return false;
714         return true;
715 }
716
717 static void atombios_crtc_prepare(struct drm_crtc *crtc)
718 {
719         atombios_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
720         atombios_lock_crtc(crtc, 1);
721 }
722
723 static void atombios_crtc_commit(struct drm_crtc *crtc)
724 {
725         atombios_crtc_dpms(crtc, DRM_MODE_DPMS_ON);
726         atombios_lock_crtc(crtc, 0);
727 }
728
729 static const struct drm_crtc_helper_funcs atombios_helper_funcs = {
730         .dpms = atombios_crtc_dpms,
731         .mode_fixup = atombios_crtc_mode_fixup,
732         .mode_set = atombios_crtc_mode_set,
733         .mode_set_base = atombios_crtc_set_base,
734         .prepare = atombios_crtc_prepare,
735         .commit = atombios_crtc_commit,
736         .load_lut = radeon_crtc_load_lut,
737 };
738
739 void radeon_atombios_init_crtc(struct drm_device *dev,
740                                struct radeon_crtc *radeon_crtc)
741 {
742         if (radeon_crtc->crtc_id == 1)
743                 radeon_crtc->crtc_offset =
744                     AVIVO_D2CRTC_H_TOTAL - AVIVO_D1CRTC_H_TOTAL;
745         drm_crtc_helper_add(&radeon_crtc->base, &atombios_helper_funcs);
746 }