LUT updates
[platform/upstream/libdrm.git] / shared-core / radeon_ms_combios.c
1 /*
2  * Copyright 2007 Jérôme Glisse
3  * All Rights Reserved.
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 (including the next
13  * paragraph) shall be included in all copies or substantial portions of the
14  * Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19  * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22  * DEALINGS IN THE SOFTWARE.
23  */
24 /*
25  * Authors:
26  *    Jérôme Glisse <glisse@freedesktop.org>
27  */
28 #include "radeon_ms.h"
29
30 extern struct radeon_ms_output radeon_ms_dac1;
31 extern struct radeon_ms_output radeon_ms_dac2;
32 extern const struct drm_output_funcs radeon_ms_output_funcs;
33
34 static struct combios_connector_chip_info *
35 radeon_ms_combios_get_connector_chip_info(struct drm_device *dev, int chip_num)
36 {
37         struct drm_radeon_private *dev_priv = dev->dev_private;
38         struct radeon_ms_rom *rom = &dev_priv->rom;
39         struct combios_header *header;
40         struct combios_connector_table *connector_table;
41         struct combios_connector_chip_info *connector_chip_info;
42         uint32_t offset;
43         int numof_chips, i;
44
45         if (rom->type != ROM_COMBIOS || rom->rom_image == NULL) {
46                 return NULL;
47         }
48         header = rom->rom.combios_header;
49         offset = header->usPointerToExtendedInitTable2;
50         if ((offset + sizeof(struct combios_connector_table)) > rom->rom_size) {
51                 DRM_INFO("[radeon_ms] wrong COMBIOS connector offset\n");
52                 return NULL;
53         }
54         if (!offset) {
55                 return NULL;
56         }
57         connector_table = (struct combios_connector_table *)
58                           &rom->rom_image[offset];
59         numof_chips = (connector_table->ucConnectorHeader &
60                        BIOS_CONNECTOR_HEADER__NUMBER_OF_CHIPS__MASK) >>
61                       BIOS_CONNECTOR_HEADER__NUMBER_OF_CHIPS__SHIFT;
62         DRM_INFO("[radeon_ms] COMBIOS number of chip: %d (table rev: %d)\n",
63                  numof_chips,
64                  (connector_table->ucConnectorHeader &
65                   BIOS_CONNECTOR_HEADER__TABLE_REVISION__MASK) >>
66                  BIOS_CONNECTOR_HEADER__TABLE_REVISION__SHIFT);
67         for (i = 0; i < numof_chips; i++) {
68                 int chip;
69
70                 connector_chip_info = &connector_table->sChipConnectorInfo[i];
71                 chip = (connector_chip_info->ucChipHeader &
72                         BIOS_CHIPINFO_HEADER__CHIP_NUMBER__MASK) >>
73                        BIOS_CHIPINFO_HEADER__CHIP_NUMBER__SHIFT;
74                 DRM_INFO("[radeon_ms] COMBIOS chip: %d (asked for: %d)\n",
75                          chip, chip_num);
76                 if (chip == chip_num) {
77                         return connector_chip_info;
78                 }
79         }
80         return NULL;
81 }
82
83 static int radeon_combios_get_connector_infos(struct drm_device *dev,
84                                               int connector_info, 
85                                               int *connector_type, 
86                                               int *ddc_line,
87                                               int *tmds_type,
88                                               int *dac_type)
89 {
90         struct drm_radeon_private *dev_priv = dev->dev_private;
91
92         *connector_type = (connector_info & BIOS_CONNECTOR_INFO__TYPE__MASK) >>
93                           BIOS_CONNECTOR_INFO__TYPE__SHIFT;
94         *ddc_line = (connector_info & BIOS_CONNECTOR_INFO__DDC_LINE__MASK) >>
95                     BIOS_CONNECTOR_INFO__DDC_LINE__SHIFT;
96         *tmds_type = (connector_info & BIOS_CONNECTOR_INFO__TMDS_TYPE__MASK) >>
97                      BIOS_CONNECTOR_INFO__TMDS_TYPE__SHIFT;
98         *dac_type = (connector_info & BIOS_CONNECTOR_INFO__DAC_TYPE__MASK) >>
99                     BIOS_CONNECTOR_INFO__DAC_TYPE__SHIFT;
100
101         /* most XPRESS chips seem to specify DDC_CRT2 for their 
102          * VGA DDC port, however DDC never seems to work on that
103          * port.  Some have reported success on DDC_MONID, so 
104          * lets see what happens with that.
105          */
106         if (dev_priv->family == CHIP_RS400 &&
107             *connector_type == BIOS_CONNECTOR_TYPE__CRT &&
108             *ddc_line == BIOS_DDC_LINE__CRT2) {
109                 *ddc_line = BIOS_DDC_LINE__MONID01;
110         }
111         /* XPRESS desktop chips seem to have a proprietary
112          * connector listed for DVI-D, try and do the right
113          * thing here.
114          */
115         if (dev_priv->family == CHIP_RS400 &&
116             *connector_type == BIOS_CONNECTOR_TYPE__PROPRIETARY) {
117                 DRM_INFO("[radeon_ms] COMBIOS Proprietary connector "
118                          "found, assuming DVI-D\n");
119                 *dac_type = 2;
120                 *tmds_type = BIOS_TMDS_TYPE__EXTERNAL;
121                 *connector_type = BIOS_CONNECTOR_TYPE__DVI_D;
122         }
123         return 0;
124 }
125
126 static int radeon_ms_combios_connector_add(struct drm_device *dev,
127                                            int connector_number,
128                                            int connector_type,
129                                            uint32_t i2c_reg)
130 {
131         struct drm_radeon_private *dev_priv = dev->dev_private;
132         struct radeon_ms_connector *connector = NULL;
133         struct drm_output *output = NULL;
134
135         connector = drm_alloc(sizeof(struct radeon_ms_connector),
136                               DRM_MEM_DRIVER);
137         if (connector == NULL) {
138                 radeon_ms_connectors_destroy(dev);
139                 return -ENOMEM;
140         }
141         memset(connector, 0, sizeof(struct radeon_ms_connector));
142         connector->monitor_type = MT_NONE;
143         connector->type = connector_type;
144         connector->i2c_reg = i2c_reg;
145
146         switch (connector->type) {
147         case CONNECTOR_VGA:
148                 sprintf(connector->name, "VGA");
149                 break;
150         case CONNECTOR_DVI_I:
151                 sprintf(connector->name, "DVI-I");
152                 break;
153         case CONNECTOR_DVI_D:
154                 sprintf(connector->name, "DVI-D");
155                 break;
156         default:
157                 sprintf(connector->name, "UNKNOWN-CONNECTOR");
158                 break;
159         }
160
161         if (i2c_reg) {
162                 connector->i2c = radeon_ms_i2c_create(dev,
163                                                       connector->i2c_reg,
164                                                       connector->name);
165                 if (connector->i2c == NULL) {
166                         radeon_ms_connectors_destroy(dev);
167                         return -ENOMEM;
168                 }
169         } else {
170                 connector->i2c = NULL;
171         }
172
173         output = drm_output_create(dev, &radeon_ms_output_funcs,
174                                    connector->type);
175         if (output == NULL) {
176                 radeon_ms_connectors_destroy(dev);
177                 return -EINVAL;
178         }
179         connector->output = output;
180         output->driver_private = connector;
181         output->possible_crtcs = 0x3;
182         dev_priv->connectors[connector_number] = connector;
183         return 0;
184 }
185
186 int radeon_ms_combios_get_properties(struct drm_device *dev)
187 {
188         struct drm_radeon_private *dev_priv = dev->dev_private;
189         struct radeon_ms_rom *rom = &dev_priv->rom;
190         struct combios_pll_block *pll_block;
191         struct combios_header *header;
192         uint32_t offset;
193
194         if (rom->type != ROM_COMBIOS || rom->rom_image == NULL) {
195                 return 0;
196         }
197         header = rom->rom.combios_header;
198         offset = header->usPointerToPllInfoBlock;
199         if ((offset + sizeof(struct combios_pll_block)) > rom->rom_size) {
200                 DRM_INFO("[radeon_ms] wrong COMBIOS pll block offset\n");
201                 return 0;
202         }
203         if (!offset) {
204                 return 0;
205         }
206         pll_block = (struct combios_pll_block *)&rom->rom_image[offset];
207         dev_priv->properties.pll_reference_freq = pll_block->usDotClockRefFreq;
208         dev_priv->properties.pll_reference_div = pll_block->usDotClockRefDiv;
209         dev_priv->properties.pll_min_pll_freq = pll_block->ulDotClockMinFreq;
210         dev_priv->properties.pll_max_pll_freq = pll_block->ulDotClockMaxFreq;
211         dev_priv->properties.pll_reference_freq *= 10;
212         dev_priv->properties.pll_min_pll_freq *= 10;
213         dev_priv->properties.pll_max_pll_freq *= 10;
214         DRM_INFO("[radeon_ms] COMBIOS pll reference frequency : %d\n",
215                  dev_priv->properties.pll_reference_freq);
216         DRM_INFO("[radeon_ms] COMBIOS pll reference divider   : %d\n",
217                  dev_priv->properties.pll_reference_div);
218         DRM_INFO("[radeon_ms] COMBIOS pll minimum frequency   : %d\n",
219                  dev_priv->properties.pll_min_pll_freq);
220         DRM_INFO("[radeon_ms] COMBIOS pll maximum frequency   : %d\n",
221                  dev_priv->properties.pll_max_pll_freq);
222         return 1;
223 }
224
225 int radeon_ms_connectors_from_combios(struct drm_device *dev)
226 {
227         struct drm_radeon_private *dev_priv = dev->dev_private;
228         struct combios_connector_chip_info *connector_chip_info;
229         int connector_type, ddc_line, tmds_type, dac_type;
230         int dac1, dac2, tmdsint, tmdsext;
231         int numof_connector, i, c = 0, added, j;
232         uint32_t i2c_reg;
233         int ret;
234
235         dac1 = dac2 = tmdsint = tmdsext = -1;
236         connector_chip_info = radeon_ms_combios_get_connector_chip_info(dev, 1);
237         if (connector_chip_info == NULL) {
238                 return -1;
239         }
240         numof_connector = (connector_chip_info->ucChipHeader &
241                            BIOS_CHIPINFO_HEADER__NUMBER_OF_CONNECTORS__MASK) >>
242                           BIOS_CHIPINFO_HEADER__NUMBER_OF_CONNECTORS__SHIFT;
243         DRM_INFO("[radeon_ms] COMBIOS number of connector: %d\n",
244                  numof_connector);
245         for (i = 0; i < numof_connector; i++) {
246                 int connector_info = connector_chip_info->sConnectorInfo[i];
247
248                 ret = radeon_combios_get_connector_infos(dev,
249                                                          connector_info, 
250                                                          &connector_type, 
251                                                          &ddc_line,
252                                                          &tmds_type,
253                                                          &dac_type);
254
255                 switch (ddc_line) {
256                 case BIOS_DDC_LINE__MONID01:
257                         i2c_reg = GPIO_MONID;
258                         break;
259                 case BIOS_DDC_LINE__DVI:
260                         i2c_reg =  GPIO_DVI_DDC;
261                         break;
262                 case BIOS_DDC_LINE__VGA:
263                         i2c_reg = GPIO_DDC1;
264                         break;
265                 case BIOS_DDC_LINE__CRT2:
266                         i2c_reg = GPIO_CRT2_DDC;
267                         break;
268                 case BIOS_DDC_LINE__GPIOPAD:
269                         i2c_reg = VIPPAD_EN;
270                         break;
271                 case BIOS_DDC_LINE__ZV_LCDPAD:
272                         i2c_reg = VIPPAD1_EN;
273                         break;
274                 default:
275                         i2c_reg = 0;
276                         break;
277                 }
278                 added = 0;
279                 switch (connector_type) {
280                 case BIOS_CONNECTOR_TYPE__CRT:
281                         ret = radeon_ms_combios_connector_add(dev, c,
282                                                               CONNECTOR_VGA,
283                                                               i2c_reg);
284                         if (ret) {
285                                 return ret;
286                         }
287                         added = 1;
288                         break;
289                 case BIOS_CONNECTOR_TYPE__DVI_I:
290                         ret = radeon_ms_combios_connector_add(dev, c,
291                                                               CONNECTOR_DVI_I,
292                                                               i2c_reg);
293                         if (ret) {
294                                 return ret;
295                         }
296                         added = 1;
297                         break;
298                 case BIOS_CONNECTOR_TYPE__DVI_D:
299                         ret = radeon_ms_combios_connector_add(dev, c,
300                                                               CONNECTOR_DVI_D,
301                                                               i2c_reg);
302                         if (ret) {
303                                 return ret;
304                         }
305                         added = 1;
306                         break;
307                 default:
308                         break;
309                 }
310                 if (added) {
311                         j = 0;
312                         /* find to which output this connector is associated 
313                          * by following same algo as in:
314                          * radeon_ms_outputs_from_combios*/
315                         switch (dac_type) {
316                         case BIOS_DAC_TYPE__CRT:
317                                 if (dac1 == -1) {
318                                         dac1 = c;
319                                 }
320                                 dev_priv->connectors[c]->outputs[j++] = dac1;
321                                 break;
322                         case BIOS_DAC_TYPE__NON_CRT:
323                                 if (dac2 == -1) {
324                                         dac2 = c;
325                                 }
326                                 dev_priv->connectors[c]->outputs[j++] = dac2;
327                                 break;
328                         }
329 #if 0
330                         switch (tmds_type) {
331                         case BIOS_TMDS_TYPE__INTERNAL:
332                                 if (tmdsint == -1) {
333                                         tmdsint = c;
334                                 }
335                                 dev_priv->connectors[c]->outputs[j++] = tmdsint;
336                                 break;
337                         case BIOS_TMDS_TYPE__EXTERNAL:
338                                 if (tmdsext == -1) {
339                                         tmdsext = c;
340                                 }
341                                 dev_priv->connectors[c]->outputs[j++] = tmdsext;
342                                 break;
343                         }
344 #endif
345                         c++;
346                 }
347         }
348         return c;
349 }
350
351 int radeon_ms_outputs_from_combios(struct drm_device *dev)
352 {
353         struct drm_radeon_private *dev_priv = dev->dev_private;
354         struct combios_connector_chip_info *connector_chip_info;
355         int connector_type, ddc_line, tmds_type, dac_type;
356         int numof_connector, i, dac1_present, dac2_present, c = 0;
357         int ret;
358
359         dac1_present = dac2_present = 0;
360         connector_chip_info = radeon_ms_combios_get_connector_chip_info(dev, 1);
361         if (connector_chip_info == NULL) {
362                 return -1;
363         }
364         numof_connector = (connector_chip_info->ucChipHeader &
365                            BIOS_CHIPINFO_HEADER__NUMBER_OF_CONNECTORS__MASK) >>
366                           BIOS_CHIPINFO_HEADER__NUMBER_OF_CONNECTORS__SHIFT;
367         DRM_INFO("[radeon_ms] COMBIOS number of connector: %d\n",
368                  numof_connector);
369         for (i = 0; i < numof_connector; i++) {
370                 int connector_info = connector_chip_info->sConnectorInfo[i];
371
372                 ret = radeon_combios_get_connector_infos(dev,
373                                                          connector_info, 
374                                                          &connector_type, 
375                                                          &ddc_line,
376                                                          &tmds_type,
377                                                          &dac_type);
378
379                 if (!dac1_present && dac_type == BIOS_DAC_TYPE__CRT) {
380                         dev_priv->outputs[c] =
381                                 drm_alloc(sizeof(struct radeon_ms_output),
382                                           DRM_MEM_DRIVER);
383                         if (dev_priv->outputs[c] == NULL) {
384                                 radeon_ms_outputs_destroy(dev);
385                                 return -ENOMEM;
386                         }
387                         memcpy(dev_priv->outputs[c], &radeon_ms_dac1,
388                                sizeof(struct radeon_ms_output));
389                         dev_priv->outputs[c]->dev = dev;
390                         dev_priv->outputs[c]->initialize(dev_priv->outputs[c]);
391                         dac1_present = 1;
392                         c++;
393                 }
394                 if (!dac2_present && dac_type == BIOS_DAC_TYPE__NON_CRT) {
395                         dev_priv->outputs[c] =
396                                 drm_alloc(sizeof(struct radeon_ms_output),
397                                           DRM_MEM_DRIVER);
398                         if (dev_priv->outputs[c] == NULL) {
399                                 radeon_ms_outputs_destroy(dev);
400                                 return -ENOMEM;
401                         }
402                         memcpy(dev_priv->outputs[c], &radeon_ms_dac2,
403                                sizeof(struct radeon_ms_output));
404                         dev_priv->outputs[c]->dev = dev;
405                         dev_priv->outputs[c]->initialize(dev_priv->outputs[c]);
406                         dac1_present = 1;
407                         c++;
408                 }
409         }
410         return c;
411 }