drm/radeon/kms/atom: add support for AdjustDisplayPll
[cascardo/linux.git] / 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                 atombios_enable_crtc(crtc, 1);
252                 if (ASIC_IS_DCE3(rdev))
253                         atombios_enable_crtc_memreq(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                 if (ASIC_IS_DCE3(rdev))
261                         atombios_enable_crtc_memreq(crtc, 0);
262                 atombios_enable_crtc(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;
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 pll_clock = mode->clock;
342         uint32_t adjusted_clock;
343         uint32_t ref_div = 0, fb_div = 0, frac_fb_div = 0, post_div = 0;
344         struct radeon_pll *pll;
345         int pll_flags = 0;
346
347         memset(&args, 0, sizeof(args));
348
349         if (ASIC_IS_AVIVO(rdev)) {
350                 uint32_t ss_cntl;
351
352                 if ((rdev->family == CHIP_RS600) ||
353                     (rdev->family == CHIP_RS690) ||
354                     (rdev->family == CHIP_RS740))
355                         pll_flags |= (RADEON_PLL_USE_FRAC_FB_DIV |
356                                       RADEON_PLL_PREFER_CLOSEST_LOWER);
357
358                 if (ASIC_IS_DCE32(rdev) && mode->clock > 200000)        /* range limits??? */
359                         pll_flags |= RADEON_PLL_PREFER_HIGH_FB_DIV;
360                 else
361                         pll_flags |= RADEON_PLL_PREFER_LOW_REF_DIV;
362
363                 /* disable spread spectrum clocking for now -- thanks Hedy Lamarr */
364                 if (radeon_crtc->crtc_id == 0) {
365                         ss_cntl = RREG32(AVIVO_P1PLL_INT_SS_CNTL);
366                         WREG32(AVIVO_P1PLL_INT_SS_CNTL, ss_cntl & ~1);
367                 } else {
368                         ss_cntl = RREG32(AVIVO_P2PLL_INT_SS_CNTL);
369                         WREG32(AVIVO_P2PLL_INT_SS_CNTL, ss_cntl & ~1);
370                 }
371         } else {
372                 pll_flags |= RADEON_PLL_LEGACY;
373
374                 if (mode->clock > 200000)       /* range limits??? */
375                         pll_flags |= RADEON_PLL_PREFER_HIGH_FB_DIV;
376                 else
377                         pll_flags |= RADEON_PLL_PREFER_LOW_REF_DIV;
378
379         }
380
381         list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
382                 if (encoder->crtc == crtc) {
383                         if (!ASIC_IS_AVIVO(rdev)) {
384                                 if (encoder->encoder_type !=
385                                     DRM_MODE_ENCODER_DAC)
386                                         pll_flags |= RADEON_PLL_NO_ODD_POST_DIV;
387                                 if (!ASIC_IS_AVIVO(rdev)
388                                     && (encoder->encoder_type ==
389                                         DRM_MODE_ENCODER_LVDS))
390                                         pll_flags |= RADEON_PLL_USE_REF_DIV;
391                         }
392                         radeon_encoder = to_radeon_encoder(encoder);
393                         break;
394                 }
395         }
396
397         /* DCE3+ has an AdjustDisplayPll that will adjust the pixel clock
398          * accordingly based on the encoder/transmitter to work around
399          * special hw requirements.
400          */
401         if (ASIC_IS_DCE3(rdev)) {
402                 ADJUST_DISPLAY_PLL_PS_ALLOCATION adjust_pll_args;
403
404                 if (!encoder)
405                         return;
406
407                 memset(&adjust_pll_args, 0, sizeof(adjust_pll_args));
408                 adjust_pll_args.usPixelClock = cpu_to_le16(mode->clock / 10);
409                 adjust_pll_args.ucTransmitterID = radeon_encoder->encoder_id;
410                 adjust_pll_args.ucEncodeMode = atombios_get_encoder_mode(encoder);
411
412                 index = GetIndexIntoMasterTable(COMMAND, AdjustDisplayPll);
413                 atom_execute_table(rdev->mode_info.atom_context,
414                                    index, (uint32_t *)&adjust_pll_args);
415                 adjusted_clock = le16_to_cpu(adjust_pll_args.usPixelClock) * 10;
416         } else
417                 adjusted_clock = mode->clock;
418
419         if (radeon_crtc->crtc_id == 0)
420                 pll = &rdev->clock.p1pll;
421         else
422                 pll = &rdev->clock.p2pll;
423
424         radeon_compute_pll(pll, adjusted_clock, &pll_clock, &fb_div, &frac_fb_div,
425                            &ref_div, &post_div, pll_flags);
426
427         atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev,
428                               &crev);
429
430         switch (frev) {
431         case 1:
432                 switch (crev) {
433                 case 1:
434                         spc1_ptr = (PIXEL_CLOCK_PARAMETERS *) & args.sPCLKInput;
435                         spc1_ptr->usPixelClock = cpu_to_le16(mode->clock / 10);
436                         spc1_ptr->usRefDiv = cpu_to_le16(ref_div);
437                         spc1_ptr->usFbDiv = cpu_to_le16(fb_div);
438                         spc1_ptr->ucFracFbDiv = frac_fb_div;
439                         spc1_ptr->ucPostDiv = post_div;
440                         spc1_ptr->ucPpll =
441                             radeon_crtc->crtc_id ? ATOM_PPLL2 : ATOM_PPLL1;
442                         spc1_ptr->ucCRTC = radeon_crtc->crtc_id;
443                         spc1_ptr->ucRefDivSrc = 1;
444                         break;
445                 case 2:
446                         spc2_ptr =
447                             (PIXEL_CLOCK_PARAMETERS_V2 *) & args.sPCLKInput;
448                         spc2_ptr->usPixelClock = cpu_to_le16(mode->clock / 10);
449                         spc2_ptr->usRefDiv = cpu_to_le16(ref_div);
450                         spc2_ptr->usFbDiv = cpu_to_le16(fb_div);
451                         spc2_ptr->ucFracFbDiv = frac_fb_div;
452                         spc2_ptr->ucPostDiv = post_div;
453                         spc2_ptr->ucPpll =
454                             radeon_crtc->crtc_id ? ATOM_PPLL2 : ATOM_PPLL1;
455                         spc2_ptr->ucCRTC = radeon_crtc->crtc_id;
456                         spc2_ptr->ucRefDivSrc = 1;
457                         break;
458                 case 3:
459                         if (!encoder)
460                                 return;
461                         spc3_ptr =
462                             (PIXEL_CLOCK_PARAMETERS_V3 *) & args.sPCLKInput;
463                         spc3_ptr->usPixelClock = cpu_to_le16(mode->clock / 10);
464                         spc3_ptr->usRefDiv = cpu_to_le16(ref_div);
465                         spc3_ptr->usFbDiv = cpu_to_le16(fb_div);
466                         spc3_ptr->ucFracFbDiv = frac_fb_div;
467                         spc3_ptr->ucPostDiv = post_div;
468                         spc3_ptr->ucPpll =
469                             radeon_crtc->crtc_id ? ATOM_PPLL2 : ATOM_PPLL1;
470                         spc3_ptr->ucMiscInfo = (radeon_crtc->crtc_id << 2);
471                         spc3_ptr->ucTransmitterId = radeon_encoder->encoder_id;
472                         spc3_ptr->ucEncoderMode =
473                             atombios_get_encoder_mode(encoder);
474                         break;
475                 default:
476                         DRM_ERROR("Unknown table version %d %d\n", frev, crev);
477                         return;
478                 }
479                 break;
480         default:
481                 DRM_ERROR("Unknown table version %d %d\n", frev, crev);
482                 return;
483         }
484
485         printk("executing set pll\n");
486         index = GetIndexIntoMasterTable(COMMAND, SetPixelClock);
487         atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
488 }
489
490 int atombios_crtc_set_base(struct drm_crtc *crtc, int x, int y,
491                            struct drm_framebuffer *old_fb)
492 {
493         struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
494         struct drm_device *dev = crtc->dev;
495         struct radeon_device *rdev = dev->dev_private;
496         struct radeon_framebuffer *radeon_fb;
497         struct drm_gem_object *obj;
498         struct drm_radeon_gem_object *obj_priv;
499         uint64_t fb_location;
500         uint32_t fb_format, fb_pitch_pixels, tiling_flags;
501
502         if (!crtc->fb)
503                 return -EINVAL;
504
505         radeon_fb = to_radeon_framebuffer(crtc->fb);
506
507         obj = radeon_fb->obj;
508         obj_priv = obj->driver_private;
509
510         if (radeon_gem_object_pin(obj, RADEON_GEM_DOMAIN_VRAM, &fb_location)) {
511                 return -EINVAL;
512         }
513
514         switch (crtc->fb->bits_per_pixel) {
515         case 8:
516                 fb_format =
517                     AVIVO_D1GRPH_CONTROL_DEPTH_8BPP |
518                     AVIVO_D1GRPH_CONTROL_8BPP_INDEXED;
519                 break;
520         case 15:
521                 fb_format =
522                     AVIVO_D1GRPH_CONTROL_DEPTH_16BPP |
523                     AVIVO_D1GRPH_CONTROL_16BPP_ARGB1555;
524                 break;
525         case 16:
526                 fb_format =
527                     AVIVO_D1GRPH_CONTROL_DEPTH_16BPP |
528                     AVIVO_D1GRPH_CONTROL_16BPP_RGB565;
529                 break;
530         case 24:
531         case 32:
532                 fb_format =
533                     AVIVO_D1GRPH_CONTROL_DEPTH_32BPP |
534                     AVIVO_D1GRPH_CONTROL_32BPP_ARGB8888;
535                 break;
536         default:
537                 DRM_ERROR("Unsupported screen depth %d\n",
538                           crtc->fb->bits_per_pixel);
539                 return -EINVAL;
540         }
541
542         radeon_object_get_tiling_flags(obj->driver_private,
543                                        &tiling_flags, NULL);
544         if (tiling_flags & RADEON_TILING_MACRO)
545                 fb_format |= AVIVO_D1GRPH_MACRO_ADDRESS_MODE;
546
547         if (tiling_flags & RADEON_TILING_MICRO)
548                 fb_format |= AVIVO_D1GRPH_TILED;
549
550         if (radeon_crtc->crtc_id == 0)
551                 WREG32(AVIVO_D1VGA_CONTROL, 0);
552         else
553                 WREG32(AVIVO_D2VGA_CONTROL, 0);
554         WREG32(AVIVO_D1GRPH_PRIMARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset,
555                (u32) fb_location);
556         WREG32(AVIVO_D1GRPH_SECONDARY_SURFACE_ADDRESS +
557                radeon_crtc->crtc_offset, (u32) fb_location);
558         WREG32(AVIVO_D1GRPH_CONTROL + radeon_crtc->crtc_offset, fb_format);
559
560         WREG32(AVIVO_D1GRPH_SURFACE_OFFSET_X + radeon_crtc->crtc_offset, 0);
561         WREG32(AVIVO_D1GRPH_SURFACE_OFFSET_Y + radeon_crtc->crtc_offset, 0);
562         WREG32(AVIVO_D1GRPH_X_START + radeon_crtc->crtc_offset, 0);
563         WREG32(AVIVO_D1GRPH_Y_START + radeon_crtc->crtc_offset, 0);
564         WREG32(AVIVO_D1GRPH_X_END + radeon_crtc->crtc_offset, crtc->fb->width);
565         WREG32(AVIVO_D1GRPH_Y_END + radeon_crtc->crtc_offset, crtc->fb->height);
566
567         fb_pitch_pixels = crtc->fb->pitch / (crtc->fb->bits_per_pixel / 8);
568         WREG32(AVIVO_D1GRPH_PITCH + radeon_crtc->crtc_offset, fb_pitch_pixels);
569         WREG32(AVIVO_D1GRPH_ENABLE + radeon_crtc->crtc_offset, 1);
570
571         WREG32(AVIVO_D1MODE_DESKTOP_HEIGHT + radeon_crtc->crtc_offset,
572                crtc->mode.vdisplay);
573         x &= ~3;
574         y &= ~1;
575         WREG32(AVIVO_D1MODE_VIEWPORT_START + radeon_crtc->crtc_offset,
576                (x << 16) | y);
577         WREG32(AVIVO_D1MODE_VIEWPORT_SIZE + radeon_crtc->crtc_offset,
578                (crtc->mode.hdisplay << 16) | crtc->mode.vdisplay);
579
580         if (crtc->mode.flags & DRM_MODE_FLAG_INTERLACE)
581                 WREG32(AVIVO_D1MODE_DATA_FORMAT + radeon_crtc->crtc_offset,
582                        AVIVO_D1MODE_INTERLEAVE_EN);
583         else
584                 WREG32(AVIVO_D1MODE_DATA_FORMAT + radeon_crtc->crtc_offset, 0);
585
586         if (old_fb && old_fb != crtc->fb) {
587                 radeon_fb = to_radeon_framebuffer(old_fb);
588                 radeon_gem_object_unpin(radeon_fb->obj);
589         }
590
591         /* Bytes per pixel may have changed */
592         radeon_bandwidth_update(rdev);
593
594         return 0;
595 }
596
597 int atombios_crtc_mode_set(struct drm_crtc *crtc,
598                            struct drm_display_mode *mode,
599                            struct drm_display_mode *adjusted_mode,
600                            int x, int y, struct drm_framebuffer *old_fb)
601 {
602         struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
603         struct drm_device *dev = crtc->dev;
604         struct radeon_device *rdev = dev->dev_private;
605         struct drm_encoder *encoder;
606         SET_CRTC_TIMING_PARAMETERS_PS_ALLOCATION crtc_timing;
607         int need_tv_timings = 0;
608         bool ret;
609
610         /* TODO color tiling */
611         memset(&crtc_timing, 0, sizeof(crtc_timing));
612
613         list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
614                 /* find tv std */
615                 if (encoder->crtc == crtc) {
616                         struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
617
618                         if (radeon_encoder->active_device & ATOM_DEVICE_TV_SUPPORT) {
619                                 struct radeon_encoder_atom_dac *tv_dac = radeon_encoder->enc_priv;
620                                 if (tv_dac) {
621                                         if (tv_dac->tv_std == TV_STD_NTSC ||
622                                             tv_dac->tv_std == TV_STD_NTSC_J ||
623                                             tv_dac->tv_std == TV_STD_PAL_M)
624                                                 need_tv_timings = 1;
625                                         else
626                                                 need_tv_timings = 2;
627                                         break;
628                                 }
629                         }
630                 }
631         }
632
633         crtc_timing.ucCRTC = radeon_crtc->crtc_id;
634         if (need_tv_timings) {
635                 ret = radeon_atom_get_tv_timings(rdev, need_tv_timings - 1,
636                                                  &crtc_timing, &adjusted_mode->clock);
637                 if (ret == false)
638                         need_tv_timings = 0;
639         }
640
641         if (!need_tv_timings) {
642                 crtc_timing.usH_Total = adjusted_mode->crtc_htotal;
643                 crtc_timing.usH_Disp = adjusted_mode->crtc_hdisplay;
644                 crtc_timing.usH_SyncStart = adjusted_mode->crtc_hsync_start;
645                 crtc_timing.usH_SyncWidth =
646                         adjusted_mode->crtc_hsync_end - adjusted_mode->crtc_hsync_start;
647
648                 crtc_timing.usV_Total = adjusted_mode->crtc_vtotal;
649                 crtc_timing.usV_Disp = adjusted_mode->crtc_vdisplay;
650                 crtc_timing.usV_SyncStart = adjusted_mode->crtc_vsync_start;
651                 crtc_timing.usV_SyncWidth =
652                         adjusted_mode->crtc_vsync_end - adjusted_mode->crtc_vsync_start;
653
654                 if (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC)
655                         crtc_timing.susModeMiscInfo.usAccess |= ATOM_VSYNC_POLARITY;
656
657                 if (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC)
658                         crtc_timing.susModeMiscInfo.usAccess |= ATOM_HSYNC_POLARITY;
659
660                 if (adjusted_mode->flags & DRM_MODE_FLAG_CSYNC)
661                         crtc_timing.susModeMiscInfo.usAccess |= ATOM_COMPOSITESYNC;
662
663                 if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE)
664                         crtc_timing.susModeMiscInfo.usAccess |= ATOM_INTERLACE;
665
666                 if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
667                         crtc_timing.susModeMiscInfo.usAccess |= ATOM_DOUBLE_CLOCK_MODE;
668         }
669
670         atombios_crtc_set_pll(crtc, adjusted_mode);
671         atombios_crtc_set_timing(crtc, &crtc_timing);
672
673         if (ASIC_IS_AVIVO(rdev))
674                 atombios_crtc_set_base(crtc, x, y, old_fb);
675         else {
676                 if (radeon_crtc->crtc_id == 0) {
677                         SET_CRTC_USING_DTD_TIMING_PARAMETERS crtc_dtd_timing;
678                         memset(&crtc_dtd_timing, 0, sizeof(crtc_dtd_timing));
679
680                         /* setup FP shadow regs on R4xx */
681                         crtc_dtd_timing.ucCRTC = radeon_crtc->crtc_id;
682                         crtc_dtd_timing.usH_Size = adjusted_mode->crtc_hdisplay;
683                         crtc_dtd_timing.usV_Size = adjusted_mode->crtc_vdisplay;
684                         crtc_dtd_timing.usH_Blanking_Time =
685                             adjusted_mode->crtc_hblank_end -
686                             adjusted_mode->crtc_hdisplay;
687                         crtc_dtd_timing.usV_Blanking_Time =
688                             adjusted_mode->crtc_vblank_end -
689                             adjusted_mode->crtc_vdisplay;
690                         crtc_dtd_timing.usH_SyncOffset =
691                             adjusted_mode->crtc_hsync_start -
692                             adjusted_mode->crtc_hdisplay;
693                         crtc_dtd_timing.usV_SyncOffset =
694                             adjusted_mode->crtc_vsync_start -
695                             adjusted_mode->crtc_vdisplay;
696                         crtc_dtd_timing.usH_SyncWidth =
697                             adjusted_mode->crtc_hsync_end -
698                             adjusted_mode->crtc_hsync_start;
699                         crtc_dtd_timing.usV_SyncWidth =
700                             adjusted_mode->crtc_vsync_end -
701                             adjusted_mode->crtc_vsync_start;
702                         /* crtc_dtd_timing.ucH_Border = adjusted_mode->crtc_hborder; */
703                         /* crtc_dtd_timing.ucV_Border = adjusted_mode->crtc_vborder; */
704
705                         if (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC)
706                                 crtc_dtd_timing.susModeMiscInfo.usAccess |=
707                                     ATOM_VSYNC_POLARITY;
708
709                         if (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC)
710                                 crtc_dtd_timing.susModeMiscInfo.usAccess |=
711                                     ATOM_HSYNC_POLARITY;
712
713                         if (adjusted_mode->flags & DRM_MODE_FLAG_CSYNC)
714                                 crtc_dtd_timing.susModeMiscInfo.usAccess |=
715                                     ATOM_COMPOSITESYNC;
716
717                         if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE)
718                                 crtc_dtd_timing.susModeMiscInfo.usAccess |=
719                                     ATOM_INTERLACE;
720
721                         if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
722                                 crtc_dtd_timing.susModeMiscInfo.usAccess |=
723                                     ATOM_DOUBLE_CLOCK_MODE;
724
725                         atombios_set_crtc_dtd_timing(crtc, &crtc_dtd_timing);
726                 }
727                 radeon_crtc_set_base(crtc, x, y, old_fb);
728                 radeon_legacy_atom_set_surface(crtc);
729         }
730         atombios_overscan_setup(crtc, mode, adjusted_mode);
731         atombios_scaler_setup(crtc);
732         return 0;
733 }
734
735 static bool atombios_crtc_mode_fixup(struct drm_crtc *crtc,
736                                      struct drm_display_mode *mode,
737                                      struct drm_display_mode *adjusted_mode)
738 {
739         if (!radeon_crtc_scaling_mode_fixup(crtc, mode, adjusted_mode))
740                 return false;
741         return true;
742 }
743
744 static void atombios_crtc_prepare(struct drm_crtc *crtc)
745 {
746         atombios_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
747         atombios_lock_crtc(crtc, 1);
748 }
749
750 static void atombios_crtc_commit(struct drm_crtc *crtc)
751 {
752         atombios_crtc_dpms(crtc, DRM_MODE_DPMS_ON);
753         atombios_lock_crtc(crtc, 0);
754 }
755
756 static const struct drm_crtc_helper_funcs atombios_helper_funcs = {
757         .dpms = atombios_crtc_dpms,
758         .mode_fixup = atombios_crtc_mode_fixup,
759         .mode_set = atombios_crtc_mode_set,
760         .mode_set_base = atombios_crtc_set_base,
761         .prepare = atombios_crtc_prepare,
762         .commit = atombios_crtc_commit,
763         .load_lut = radeon_crtc_load_lut,
764 };
765
766 void radeon_atombios_init_crtc(struct drm_device *dev,
767                                struct radeon_crtc *radeon_crtc)
768 {
769         if (radeon_crtc->crtc_id == 1)
770                 radeon_crtc->crtc_offset =
771                     AVIVO_D2CRTC_H_TOTAL - AVIVO_D1CRTC_H_TOTAL;
772         drm_crtc_helper_add(&radeon_crtc->base, &atombios_helper_funcs);
773 }