Efika MX platform support
[efikamx:linux-kernel.git] / arch / arm / mach-mx5 / mx51_efikamx_display.c
1 /*
2  * Copyright 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved.
3  * Copyright 2009-2010 Pegatron Corporation. All Rights Reserved.
4  * Copyright 2009-2010 Genesi USA, Inc. All Rights Reserved.
5  */
6
7 /*
8  * The code contained herein is licensed under the GNU General Public
9  * License. You may obtain a copy of the GNU General Public License
10  * Version 2 or later at the following locations:
11  *
12  * http://www.opensource.org/licenses/gpl-license.html
13  * http://www.gnu.org/copyleft/gpl.html
14  */
15
16 #include <linux/types.h>
17 #include <linux/delay.h>
18 #include <linux/pm.h>
19 #include <linux/interrupt.h>
20 #include <linux/irq.h>
21 #include <linux/init.h>
22 #include <linux/clk.h>
23 #include <linux/platform_device.h>
24 #include <linux/fsl_devices.h>
25 #include <linux/spi/spi.h>
26 #include <linux/i2c.h>
27 #include <linux/ipu.h>
28 #include <linux/mxcfb.h>
29 #include <mach/common.h>
30 #include <mach/hardware.h>
31 #include <asm/setup.h>
32 #include <asm/mach-types.h>
33 #include <asm/mach/arch.h>
34 #include <mach/gpio.h>
35 #include <mach/mxc_edid.h>
36
37 #include "devices.h"
38 #include "iomux.h"
39 #include "mx51_pins.h"
40
41 #include "mx51_efikamx.h"
42
43 int sii9022_reinit(struct fb_var_screeninfo *var);
44 int cs8556_reinit(struct fb_var_screeninfo *var);
45
46 #define VIDEO_MODE_HDMI_DEF     4
47 #define VIDEO_MODE_VGA_DEF      2
48
49 #define MEGA              1000000
50
51 int __initdata video_output = { VIDEO_OUT_STATIC_HDMI };
52 int __initdata video_mode = { VIDEO_OUT_STATIC_HDMI };
53 int __initdata hdmi_audio_auto_sw = { 0 };
54 int __initdata hdmi_audio = { 1 };
55 int __initdata enable_hdmi_spdif = { 0 };
56 int __initdata clock_auto = { 1 };
57 char __initdata vmode[32] = { 0 };
58 int __initdata mxc_debug = { 1 };
59 int __initdata extsync = { 1 };
60 int __initdata sink_dvi = { 0 };                /* default is HDMI */
61 int __initdata sink_monitor = { 0 };    /* default is TV */
62 int __initdata pixclk_limit = { 8000 }; /* 125MHz */
63 int __initdata video_max_res = { 0 };   /* use supported max resolution in edid modelist */
64 int __initdata video_1080p = { 0 };
65 /* if video_1080p is true, pixclk_limit will set to 6000, up to 1920x1080.
66   * otherwise pixclk_limit is set to 8000
67   */
68
69 u8 edid[256];
70
71 EXPORT_SYMBOL(hdmi_audio_auto_sw);
72 EXPORT_SYMBOL(hdmi_audio);
73 EXPORT_SYMBOL(enable_hdmi_spdif);
74 EXPORT_SYMBOL(clock_auto);
75 EXPORT_SYMBOL(vmode);
76 EXPORT_SYMBOL(mxc_debug);
77 EXPORT_SYMBOL(extsync);
78 EXPORT_SYMBOL(video_output);
79 EXPORT_SYMBOL(video_mode);
80
81 struct fb_videomode __initdata  preferred_mode;
82
83 static struct mxc_iomux_pin_cfg __initdata mx51_efikamx_display_iomux_pins[] = {
84         /* display reset pin */
85         {
86          MX51_PIN_DISPB2_SER_DIN, IOMUX_CONFIG_GPIO,
87          0,
88          MUX_IN_GPIO3_IPP_IND_G_IN_5_SELECT_INPUT,
89          INPUT_CTL_PATH1,
90          },
91 };
92
93 extern int sii9022_reinit(struct fb_var_screeninfo *var);
94 int mxcfb_initialized = 0;
95
96 void mx51_efikamx_display_reset(void)
97 {
98         gpio_direction_output(IOMUX_TO_GPIO(MX51_PIN_DISPB2_SER_DIN), 0);
99         gpio_set_value(IOMUX_TO_GPIO(MX51_PIN_DISPB2_SER_DIN), 0);
100         msleep(50);
101
102         /* do reset */
103         gpio_set_value(IOMUX_TO_GPIO(MX51_PIN_DISPB2_SER_DIN), 1);
104         msleep(20);             /* tRES >= 50us */
105
106         gpio_set_value(IOMUX_TO_GPIO(MX51_PIN_DISPB2_SER_DIN), 0);
107 }
108
109
110 static struct resource mxcfb_resources[] = {
111         [0] = {
112                 .flags = IORESOURCE_MEM,
113                 },
114 };
115
116 static struct mxc_fb_platform_data mxcfb_data[] = {
117         {
118                 .interface_pix_fmt = IPU_PIX_FMT_RGB24,
119                 .mode_str = "800x600-16@60", // safe default for HDMI
120         },
121         {
122                 .interface_pix_fmt = IPU_PIX_FMT_RGB565,
123                 .mode_str = "800x600-16@60", // safe default for VGA
124         },
125 };
126
127 extern void mx5_ipu_reset(void);
128 static struct mxc_ipu_config mxc_ipu_data = {
129         .rev = 2,
130         .reset = mx5_ipu_reset,
131 };
132
133 extern void mx5_vpu_reset(void);
134 static struct mxc_vpu_platform_data mxc_vpu_data = {
135         .reset = mx5_vpu_reset,
136 };
137
138
139 int mxcfb_read_edid2(struct i2c_adapter *adp, char *edid, u16 len, struct fb_var_screeninfo *einfo, int *dvi)
140 {
141         int i;
142         u8 buf0[2] = {0, 0};
143         int dat = 0;
144         u16 addr = 0x50;
145         struct i2c_msg msg[2] = {
146                 {
147                 .addr   = addr,
148                 .flags  = 0,
149                 .len    = 1,
150                 .buf    = buf0,
151                 }, {
152                 .addr   = addr,
153                 .flags  = I2C_M_RD,
154                 .len    = 128,
155                 .buf    = edid,
156                 },
157         };
158
159         printk("%s \n", __func__ );
160
161         if (adp == NULL || einfo == NULL)
162                 return -EINVAL;
163
164         buf0[0] = 0x00;
165         memset(edid, 0, len);
166         memset(einfo, 0, sizeof(struct fb_var_screeninfo));
167         msg[1].len = len;
168         dat = i2c_transfer(adp, msg, 2);
169
170         /* If 0x50 fails, try 0x37. */
171         if (edid[1] == 0x00) {
172                 msg[0].addr = msg[1].addr = 0x37;
173                 dat = i2c_transfer(adp, msg, 2);
174         }
175
176         if (edid[1] == 0x00)
177                 return -ENOENT;
178
179         *dvi = 0;
180         if ((edid[20] == 0x80) || (edid[20] == 0x88) || (edid[20] == 0))
181                 *dvi = 1;
182
183         dat = fb_parse_edid(edid, einfo);
184         if (dat)
185                 return -dat;
186
187         /* This is valid for version 1.3 of the EDID */
188         if ((edid[18] == 1) && (edid[19] == 3)) {
189                 einfo->height = edid[21] * 10;
190                 einfo->width = edid[22] * 10;
191         }
192
193         for(i=0; i< len; i+=32) {
194            int j=0;
195
196            for(j=0; j<32; j++) {
197                   printk("%02x", edid[i+j] );
198            }
199            printk("\n");
200         }
201
202         return 0;
203 }
204
205 void mxcfb_dump_modeline( struct fb_videomode *modedb, int num)
206 {
207         int i;
208         struct fb_videomode *mode;
209
210         for (i = 0; i < num; i++) {
211
212                 mode = &modedb[i];
213
214                 printk("   \"%dx%d%s%d\" %lu.%02lu ",
215                         mode->xres, mode->yres, (mode->vmode & FB_VMODE_INTERLACED) ? "i@" : "@", mode->refresh,
216                         (PICOS2KHZ(mode->pixclock) * 1000UL)/1000000,
217                         (PICOS2KHZ(mode->pixclock) ) % 1000);
218                 printk("%d %d %d %d ",
219                         mode->xres,
220                         mode->xres + mode->right_margin,
221                         mode->xres + mode->right_margin + mode->hsync_len,
222                         mode->xres + mode->right_margin + mode->hsync_len + mode->left_margin );
223                 printk("%d %d %d %d ",
224                         mode->yres,
225                         mode->yres + mode->lower_margin,
226                         mode->yres + mode->lower_margin + mode->vsync_len,
227                         mode->yres + mode->lower_margin + mode->vsync_len + mode->upper_margin );
228                 printk("%shsync %svsync\n", (mode->sync & FB_SYNC_HOR_HIGH_ACT) ? "+" : "-",
229                            (mode->sync & FB_SYNC_VERT_HIGH_ACT) ? "+" : "-" );
230
231         }
232 }
233
234 static int mxcfb_dump_mode( const char *func_char, const struct fb_videomode *mode)
235 {
236         if ( mode == NULL )
237                 return -1;
238
239         printk(KERN_INFO "%s geometry %u %u %u\n",
240           func_char,  mode->xres, mode->yres, mode->pixclock);
241         printk(KERN_INFO "%s timings %u %u %u %u %u %u %u\n",
242           func_char, mode->pixclock, mode->left_margin, mode->right_margin,
243           mode->upper_margin, mode->lower_margin, mode->hsync_len, mode->vsync_len );
244         printk(KERN_INFO "%s flag %u sync %u vmode %u %s\n",
245           func_char, mode->flag, mode->sync, mode->vmode, mode->flag & FB_MODE_IS_FIRST ? "preferred" : "" );
246
247         return 0;
248 }
249
250
251 void mxcfb_videomode_to_modelist(const struct fb_info *info, const struct fb_videomode *modedb, int num,
252                               struct list_head *head)
253 {
254         int i, del = 0;
255         INIT_LIST_HEAD(head);
256
257         for (i = 0; i < num; i++) {
258                 struct list_head *pos, *n;
259                 struct fb_modelist *modelist;
260
261                 del = 0;
262
263                 if ( modedb[i].pixclock < pixclk_limit ) {
264                         printk(KERN_INFO "%ux%u%s%u pclk=%u removed (exceed limit)\n",
265                                 modedb[i].xres, modedb[i].yres,
266                                 (modedb[i].vmode & FB_VMODE_INTERLACED ) ? "i@" : "@",
267                                 modedb[i].refresh,
268                                 modedb[i].pixclock );
269                         continue;
270                 }
271                 else if ( (modedb[i].vmode & FB_VMODE_INTERLACED) ) {
272                         printk(KERN_INFO "%ux%u%s%u pclk=%u removed (interlaced)\n",
273                                 modedb[i].xres, modedb[i].yres,
274                                 (modedb[i].vmode & FB_VMODE_INTERLACED ) ? "i@" : "@",
275                                 modedb[i].refresh,
276                                 modedb[i].pixclock );
277                         continue;
278                 }
279
280                 list_for_each_safe(pos, n, head) {
281                         modelist = list_entry(pos, struct fb_modelist, list);
282
283                         if ( res_matches_refresh(modelist->mode,
284                                                 modedb[i].xres, modedb[i].yres, modedb[i].refresh) ) {
285
286                                 /* if candidate is a detail timing, delete existing one in modelist !
287                                   * note: some TV has 1280x720@60 in standard timings but also has 1280x720 in detail timing block 
288                                   *         in this case, use detail timing !
289                                   */
290                                 if ( modedb[i].flag & FB_MODE_IS_DETAILED ) {
291
292                                         printk(KERN_INFO "%ux%u%s%u pclk=%u removed (duplicate)\n",
293                                                 modelist->mode.xres, modelist->mode.yres, 
294                                                 (modelist->mode.vmode & FB_VMODE_INTERLACED ) ? "i@" : "@",
295                                                 modelist->mode.refresh,
296                                                 modelist->mode.pixclock );
297                                         list_del(pos);
298                                         kfree(pos);
299                                         del = 1;
300                                 }
301                         }
302                 }
303
304                 if ( del == 0 )
305                         fb_add_videomode(&modedb[i], head);
306
307         }
308
309 }
310
311 void mxcfb_sanitize_modelist(const struct fb_info *info, const struct fb_videomode *modedb, int num,
312                               struct list_head *head)
313 {
314         struct fb_videomode *pmode;
315         int i;
316
317         pmode = (struct fb_videomode *) fb_find_best_display(&info->monspecs, head);
318         if (pmode)
319         {
320                 //fb_dump_mode("PREFERRED", pmode);
321                 memcpy((void *) &preferred_mode, (const void *) pmode, sizeof(struct fb_videomode));
322         }
323
324         for (i = 0; i < num; i++) {
325
326                 struct list_head *pos, *n;
327                 struct fb_modelist *modelist;
328
329                 list_for_each_safe(pos, n, head) {
330                         modelist = list_entry(pos, struct fb_modelist, list);
331                         if (PICOS2KHZ(modelist->mode.pixclock) > 133000 ) {
332                                 printk(KERN_INFO "%ux%u%s%u pclk=%u removed (pixclk higher than %lu limit)\n",
333                                         modelist->mode.xres, modelist->mode.yres,
334                                         (modelist->mode.vmode & FB_VMODE_INTERLACED ) ? "i@" : "@",
335                                         modelist->mode.refresh,
336                                         modelist->mode.pixclock, KHZ2PICOS(133000) );
337
338                                 if (0 == memcmp((void *) &preferred_mode, (void *) &modelist->mode, sizeof(struct fb_videomode)))
339                                 {
340                                         printk(KERN_INFO "uh-oh! deleted preferred mode!\n");
341                                 }
342                                 list_del(pos);
343                                 kfree(pos);
344                         }
345                 }
346
347         }
348 }
349
350 int mxcfb_handle_edid2(struct i2c_adapter *adp, char *buffer, u16 len)
351 {
352         int err = 0;
353         int dvi = 0;
354         struct fb_var_screeninfo screeninfo;
355
356         memset(&screeninfo, 0, sizeof(screeninfo));
357
358         if (cpu_is_mx51_rev(CHIP_REV_3_0) > 0) {
359                 gpio_set_value(IOMUX_TO_GPIO(MX51_PIN_CSI2_HSYNC), 1);
360                 msleep(1);
361         }
362
363         err = mxcfb_read_edid2(adp, buffer, len, &screeninfo, &dvi);
364
365         if (cpu_is_mx51_rev(CHIP_REV_3_0) > 0)
366                 gpio_set_value(IOMUX_TO_GPIO(MX51_PIN_CSI2_HSYNC), 0);
367
368
369         if ( err )
370                 printk("read_edid error!\n");
371
372         return err;
373 }
374
375 void mxcfb_clock_update(const char *clk_name_parent, unsigned long parent_rate,
376                                         const char *clk_name_this, unsigned long divider)
377 {
378         struct clk *clk, *di_clk;
379         int ret=0, ret1=0;
380
381         clk = clk_get(NULL, clk_name_parent);
382         di_clk = clk_get(NULL, clk_name_this);
383
384         clk_disable(clk);
385         clk_disable(di_clk);
386
387         printk("orig: parent=%s clk=%lu ", clk_name_parent, clk_get_rate(clk) );
388         printk("this=%s di_clk=%lu\n", clk_name_this, clk_get_rate(di_clk));
389         ret = clk_set_rate(clk, parent_rate);
390         ret1 = clk_set_rate(di_clk, parent_rate / divider);
391
392         printk("adjust: parent=%s clk=%lu ", clk_name_parent, clk_get_rate(clk));
393         printk("this=%s di_clk=%lu ret=%d ret=%d\n", clk_name_this, clk_get_rate(di_clk), ret, ret1);
394         clk_enable(clk);
395         clk_enable(di_clk);
396
397         clk_put(di_clk);
398         clk_put(clk);
399 }
400
401 int mxcfb_di_clock_adjust(int video_output, u32 pixel_clock)
402 {
403         char *clk_di = "ipu_di0_clk";
404         u32 rate = 0;
405         static u32 pixel_clock_last = 0;
406         static int video_output_last = 0;
407
408         if( clock_auto == 0 )
409                 return 0;
410
411         /* avoid uncessary clock change to reduce unknown impact chance */
412         if ( pixel_clock && (pixel_clock == pixel_clock_last) && video_output == video_output_last ) {
413                 printk(KERN_INFO "pclk %u same to previous one, skipping!\n", pixel_clock );
414                 return 0;
415         }
416         if ( pixel_clock < 6000 || pixel_clock > 40000 ) { /* 25Mhz~148Mhz */
417                 printk(KERN_INFO "pclk %u exceed limitation (6000~40000)!\n", pixel_clock );
418                 return -1;
419         }
420         pixel_clock_last = pixel_clock;
421         video_output_last = video_output;
422
423         if( video_output == VIDEO_OUT_STATIC_HDMI ) {
424                 clk_di = "ipu_di0_clk"; //hdmi
425         }
426 #if defined(CONFIG_FB_MXC_CS8556)
427         else {
428                 clk_di = "ipu_di1_clk"; //vga
429         }
430 #endif
431
432 #define MEGA 1000000
433         if ( pixel_clock == 0 ) {
434                 printk(KERN_INFO "%s invalid pclk, reset rate to %u\n",
435                         __func__, 260*MEGA );
436                 rate = 260*MEGA;
437         }
438         else {
439                 /* workaround for CVBS connector */
440                 if (pixel_clock == 37000 ) /* NTSC 480i */
441                         rate = (u32) ((((PICOS2KHZ(pixel_clock)))/1000)*1000000)*2;
442                 else
443                         rate =  (((u32)(PICOS2KHZ(pixel_clock) ))*1000 * 2);
444         }
445
446         printk("%s pixelclk=%u rate=%u\n", __func__, pixel_clock, rate );
447
448         mxcfb_clock_update("pll3", rate, clk_di, 2);
449
450         return 0;
451
452 }
453
454 void mxcfb_adjust(struct fb_var_screeninfo *var )
455 {
456         if( clock_auto )
457                 mxcfb_di_clock_adjust( video_output, var->pixclock );
458
459         if ( (video_output == VIDEO_OUT_STATIC_HDMI)) {
460                 sii9022_reinit( var );
461         }
462 #if defined(CONFIG_FB_MXC_CS8556)
463         else if ( video_output == VIDEO_OUT_STATIC_DSUB ) { /* VGA */
464                 cs8556_reinit( var );
465         }
466 #endif
467 }
468
469 void mxcfb_update_default_var(struct fb_var_screeninfo *var,
470                                 struct fb_info *info,
471                                 const struct fb_videomode *def_mode )
472 {
473         struct fb_monspecs *specs = &info->monspecs;
474         const struct fb_videomode *mode = NULL;
475         struct fb_var_screeninfo var_tmp;
476         int modeidx = 0;
477
478         printk(KERN_INFO "%s mode_opt=%s vmode=%s\n", __func__ , fb_mode_option, vmode );
479
480         /* user specified vmode,  ex: support reduce blanking, such as 1280x768MR-16@60 */
481         if ( vmode[0] ) {
482                 /* use edid support modedb or modedb in modedb.c */
483                 modeidx = fb_find_mode(var, info, vmode, specs->modedb, specs->modedb_len, def_mode, 16);
484         }
485         else if ( specs->modedb ) {
486
487                 fb_videomode_to_var( &var_tmp, def_mode);
488                 mode = fb_find_nearest_mode( def_mode, &info->modelist );
489
490                 if ( mode ) {
491                         fb_videomode_to_var(var, mode);
492                         printk(KERN_INFO "%ux%u@%u pclk=%u nearest mode is %ux%u@%u pclk=%u\n",
493                                 def_mode->xres, def_mode->yres, def_mode->refresh, def_mode->pixclock,
494                                 mode->xres, mode->yres, mode->refresh, mode->pixclock );
495                         mxcfb_dump_mode( "nearest mode", mode);
496                 }
497         }
498
499         if ( modeidx == 0 && mode == NULL ) { /* no best monitor support mode timing found, use def_video_mode timing ! */
500
501                 fb_videomode_to_var(var, def_mode);
502         }
503 }
504
505 void __init mx51_efikamx_init_display(void)
506 {
507         CONFIG_IOMUX(mx51_efikamx_display_iomux_pins);
508
509         /* Deassert VGA reset to free i2c bus */
510         gpio_request(IOMUX_TO_GPIO(MX51_PIN_EIM_A19), "vga_reset");
511         gpio_direction_output(IOMUX_TO_GPIO(MX51_PIN_EIM_A19), 1);
512
513         /* LCD related gpio */
514         gpio_request(IOMUX_TO_GPIO(MX51_PIN_DI1_D1_CS), "lcd_gpio");
515         gpio_direction_output(IOMUX_TO_GPIO(MX51_PIN_DI1_D1_CS), 0);
516
517         /* DVI Reset - Assert for i2c disabled mode */
518         gpio_request(IOMUX_TO_GPIO(MX51_PIN_DISPB2_SER_DIN), "dvi_reset");
519         gpio_direction_output(IOMUX_TO_GPIO(MX51_PIN_DISPB2_SER_DIN), 0);
520
521         /* DVI Power-down */
522         gpio_request(IOMUX_TO_GPIO(MX51_PIN_DISPB2_SER_DIO), "dvi_power");
523         gpio_direction_output(IOMUX_TO_GPIO(MX51_PIN_DISPB2_SER_DIO), 1);
524
525         mxc_register_device(&mxc_ipu_device, &mxc_ipu_data);
526         mxc_register_device(&mxcvpu_device, &mxc_vpu_data);
527         mxc_register_device(&gpu_device, NULL);
528 }
529
530 /* name is not my choice but.... */
531 int mxc_init_fb(void)
532 {
533         if ( mxcfb_initialized )
534                 return 0;
535
536         mxcfb_initialized = 1;
537
538         if ( video_1080p ) {
539                 pixclk_limit = KHZ2PICOS(149250);
540                 video_max_res = 1;
541         }
542
543         printk("*** %s vmode=%s video-mode=%d clock_auto=%d pixclk_limit=%d video_1080p=%d\n", 
544                   __func__, vmode, video_mode, clock_auto, pixclk_limit, video_1080p );
545
546         if( video_output == VIDEO_OUT_STATIC_HDMI )
547         {
548                 mxc_fb_devices[0].num_resources = ARRAY_SIZE(mxcfb_resources);
549                 mxc_fb_devices[0].resource = mxcfb_resources;
550                 printk(KERN_INFO "registering framebuffer for HDMI\n");
551                 mxc_register_device(&mxc_fb_devices[0], &mxcfb_data[0]);        // HDMI
552         }
553 #if defined(CONFIG_FB_MXC_CS8556)
554         else
555         {
556                 mxc_fb_devices[1].num_resources = ARRAY_SIZE(mxcfb_resources);
557                 mxc_fb_devices[1].resource = mxcfb_resources;
558                 mxc_register_device(&mxc_fb_devices[1], &mxcfb_data[1]);        // VGA
559         }
560 #endif
561
562         printk(KERN_INFO "registering framebuffer for VPU overlay\n");
563         mxc_register_device(&mxc_fb_devices[2], NULL);          // Overlay for VPU
564
565         return 0;
566 }
567 //device_initcall(mxcfb_init_fb);
568
569 void mx51_efikamx_display_adjust_mem(int gpu_start, int gpu_mem, int fb_mem)
570 {
571                 /*reserve memory for gpu*/
572                 gpu_device.resource[5].start = gpu_start;
573                 gpu_device.resource[5].end =
574                                 gpu_device.resource[5].start + gpu_mem - 1;
575                 if (fb_mem) {
576                         mxcfb_resources[0].start =
577                                 gpu_device.resource[5].end + 1;
578                         mxcfb_resources[0].end =
579                                 mxcfb_resources[0].start + fb_mem - 1;
580                 } else {
581                         mxcfb_resources[0].start = 0;
582                         mxcfb_resources[0].end = 0;
583                 }
584 }
585
586
587
588 static int __init vga_setup(char *__unused)
589 {
590         video_output = VIDEO_OUT_STATIC_DSUB;
591         return 1;
592 }
593
594 static int __init hdmi_setup(char *__unused)
595 {
596         video_output = VIDEO_OUT_STATIC_HDMI;
597         return 1;
598 }
599
600 static int __init hdmi_spdif_setup(char *__unused)
601 {
602         enable_hdmi_spdif = 1;
603         return 1;
604 }
605
606 static int __init hdmi_audio_auto_sw_setup(char *options)
607 {
608         if (!options || !*options)
609                 return 1;
610
611         hdmi_audio_auto_sw = simple_strtol(options, NULL, 10);
612
613         printk("hdmi audio auto switch=%d\n", hdmi_audio_auto_sw);
614
615         return 1;
616 }
617
618 static int __init video_mode_setup(char *options)
619 {
620         if (!options || !*options)
621                 return 1;
622
623         video_mode = simple_strtol(options, NULL, 10);
624         
625         printk("video mode=%d\n", video_mode);
626
627         return 1;
628 }
629
630 static int __init clock_setup(char *options)
631 {       
632         if (!options || !*options)
633                 return 1;
634         
635         clock_auto = simple_strtol(options, NULL, 10);
636         printk("clock_auto=%d\n", clock_auto);
637         
638         return 1;
639 }
640
641 static int __init vmode_setup(char *options)
642 {
643         if (!options || !*options)
644                 return 1;
645
646         memset( vmode, 0, sizeof(vmode));
647         strncpy( vmode, options, sizeof(vmode)-1 );
648         printk("vmode=%s\n", vmode );
649         
650         return 1;
651 }
652
653 static int __init video_max_res_setup(char *options)
654 {
655         if (!options || !*options)
656                 return 1;
657         
658         video_max_res = simple_strtol(options, NULL, 10);
659         printk("video_max_res=%d\n", video_max_res);
660         
661         return 1;
662 }
663
664 static int __init video_1080p_setup(char *options)
665 {
666         if (!options || !*options)
667                 return 1;
668         
669         video_1080p = simple_strtol(options, NULL, 10);
670         printk("video_1080p=%d\n", video_1080p);
671
672         return 1;
673 }
674
675 __setup("vga", vga_setup);
676 __setup("hdmi", hdmi_setup);
677 __setup("spdif", hdmi_spdif_setup);
678 __setup("hdmi_audio_auto_sw=", hdmi_audio_auto_sw_setup);
679 __setup("video_mode=", video_mode_setup);
680 __setup("clock_auto=", clock_setup);
681 __setup("vmode=", vmode_setup);
682 __setup("video_max_res=", video_max_res_setup);
683 __setup("video_1080p=", video_1080p_setup);