diff options
Diffstat (limited to 'arch/arm/mach-davinci/board-dm646x-evm.c')
-rw-r--r-- | arch/arm/mach-davinci/board-dm646x-evm.c | 410 |
1 files changed, 410 insertions, 0 deletions
diff --git a/arch/arm/mach-davinci/board-dm646x-evm.c b/arch/arm/mach-davinci/board-dm646x-evm.c index 8657e72debc1..24e0e13b1492 100644 --- a/arch/arm/mach-davinci/board-dm646x-evm.c +++ b/arch/arm/mach-davinci/board-dm646x-evm.c | |||
@@ -34,6 +34,8 @@ | |||
34 | #include <linux/i2c/pcf857x.h> | 34 | #include <linux/i2c/pcf857x.h> |
35 | #include <linux/etherdevice.h> | 35 | #include <linux/etherdevice.h> |
36 | 36 | ||
37 | #include <media/tvp514x.h> | ||
38 | |||
37 | #include <asm/setup.h> | 39 | #include <asm/setup.h> |
38 | #include <asm/mach-types.h> | 40 | #include <asm/mach-types.h> |
39 | #include <asm/mach/arch.h> | 41 | #include <asm/mach/arch.h> |
@@ -48,13 +50,89 @@ | |||
48 | #include <mach/mmc.h> | 50 | #include <mach/mmc.h> |
49 | #include <mach/emac.h> | 51 | #include <mach/emac.h> |
50 | 52 | ||
53 | #if defined(CONFIG_BLK_DEV_PALMCHIP_BK3710) || \ | ||
54 | defined(CONFIG_BLK_DEV_PALMCHIP_BK3710_MODULE) | ||
55 | #define HAS_ATA 1 | ||
56 | #else | ||
57 | #define HAS_ATA 0 | ||
58 | #endif | ||
59 | |||
60 | /* CPLD Register 0 bits to control ATA */ | ||
61 | #define DM646X_EVM_ATA_RST BIT(0) | ||
62 | #define DM646X_EVM_ATA_PWD BIT(1) | ||
63 | |||
51 | #define DM646X_EVM_PHY_MASK (0x2) | 64 | #define DM646X_EVM_PHY_MASK (0x2) |
52 | #define DM646X_EVM_MDIO_FREQUENCY (2200000) /* PHY bus frequency */ | 65 | #define DM646X_EVM_MDIO_FREQUENCY (2200000) /* PHY bus frequency */ |
53 | 66 | ||
67 | #define VIDCLKCTL_OFFSET (DAVINCI_SYSTEM_MODULE_BASE + 0x38) | ||
68 | #define VSCLKDIS_OFFSET (DAVINCI_SYSTEM_MODULE_BASE + 0x6c) | ||
69 | #define VCH2CLK_MASK (BIT_MASK(10) | BIT_MASK(9) | BIT_MASK(8)) | ||
70 | #define VCH2CLK_SYSCLK8 (BIT(9)) | ||
71 | #define VCH2CLK_AUXCLK (BIT(9) | BIT(8)) | ||
72 | #define VCH3CLK_MASK (BIT_MASK(14) | BIT_MASK(13) | BIT_MASK(12)) | ||
73 | #define VCH3CLK_SYSCLK8 (BIT(13)) | ||
74 | #define VCH3CLK_AUXCLK (BIT(14) | BIT(13)) | ||
75 | |||
76 | #define VIDCH2CLK (BIT(10)) | ||
77 | #define VIDCH3CLK (BIT(11)) | ||
78 | #define VIDCH1CLK (BIT(4)) | ||
79 | #define TVP7002_INPUT (BIT(4)) | ||
80 | #define TVP5147_INPUT (~BIT(4)) | ||
81 | #define VPIF_INPUT_ONE_CHANNEL (BIT(5)) | ||
82 | #define VPIF_INPUT_TWO_CHANNEL (~BIT(5)) | ||
83 | #define TVP5147_CH0 "tvp514x-0" | ||
84 | #define TVP5147_CH1 "tvp514x-1" | ||
85 | |||
86 | static void __iomem *vpif_vidclkctl_reg; | ||
87 | static void __iomem *vpif_vsclkdis_reg; | ||
88 | /* spin lock for updating above registers */ | ||
89 | static spinlock_t vpif_reg_lock; | ||
90 | |||
54 | static struct davinci_uart_config uart_config __initdata = { | 91 | static struct davinci_uart_config uart_config __initdata = { |
55 | .enabled_uarts = (1 << 0), | 92 | .enabled_uarts = (1 << 0), |
56 | }; | 93 | }; |
57 | 94 | ||
95 | /* CPLD Register 0 Client: used for I/O Control */ | ||
96 | static int cpld_reg0_probe(struct i2c_client *client, | ||
97 | const struct i2c_device_id *id) | ||
98 | { | ||
99 | if (HAS_ATA) { | ||
100 | u8 data; | ||
101 | struct i2c_msg msg[2] = { | ||
102 | { | ||
103 | .addr = client->addr, | ||
104 | .flags = I2C_M_RD, | ||
105 | .len = 1, | ||
106 | .buf = &data, | ||
107 | }, | ||
108 | { | ||
109 | .addr = client->addr, | ||
110 | .flags = 0, | ||
111 | .len = 1, | ||
112 | .buf = &data, | ||
113 | }, | ||
114 | }; | ||
115 | |||
116 | /* Clear ATA_RSTn and ATA_PWD bits to enable ATA operation. */ | ||
117 | i2c_transfer(client->adapter, msg, 1); | ||
118 | data &= ~(DM646X_EVM_ATA_RST | DM646X_EVM_ATA_PWD); | ||
119 | i2c_transfer(client->adapter, msg + 1, 1); | ||
120 | } | ||
121 | |||
122 | return 0; | ||
123 | } | ||
124 | |||
125 | static const struct i2c_device_id cpld_reg_ids[] = { | ||
126 | { "cpld_reg0", 0, }, | ||
127 | { }, | ||
128 | }; | ||
129 | |||
130 | static struct i2c_driver dm6467evm_cpld_driver = { | ||
131 | .driver.name = "cpld_reg0", | ||
132 | .id_table = cpld_reg_ids, | ||
133 | .probe = cpld_reg0_probe, | ||
134 | }; | ||
135 | |||
58 | /* LEDS */ | 136 | /* LEDS */ |
59 | 137 | ||
60 | static struct gpio_led evm_leds[] = { | 138 | static struct gpio_led evm_leds[] = { |
@@ -206,6 +284,69 @@ static struct at24_platform_data eeprom_info = { | |||
206 | .context = (void *)0x7f00, | 284 | .context = (void *)0x7f00, |
207 | }; | 285 | }; |
208 | 286 | ||
287 | static u8 dm646x_iis_serializer_direction[] = { | ||
288 | TX_MODE, RX_MODE, INACTIVE_MODE, INACTIVE_MODE, | ||
289 | }; | ||
290 | |||
291 | static u8 dm646x_dit_serializer_direction[] = { | ||
292 | TX_MODE, | ||
293 | }; | ||
294 | |||
295 | static struct snd_platform_data dm646x_evm_snd_data[] = { | ||
296 | { | ||
297 | .tx_dma_offset = 0x400, | ||
298 | .rx_dma_offset = 0x400, | ||
299 | .op_mode = DAVINCI_MCASP_IIS_MODE, | ||
300 | .num_serializer = ARRAY_SIZE(dm646x_iis_serializer_direction), | ||
301 | .tdm_slots = 2, | ||
302 | .serial_dir = dm646x_iis_serializer_direction, | ||
303 | .eventq_no = EVENTQ_0, | ||
304 | }, | ||
305 | { | ||
306 | .tx_dma_offset = 0x400, | ||
307 | .rx_dma_offset = 0, | ||
308 | .op_mode = DAVINCI_MCASP_DIT_MODE, | ||
309 | .num_serializer = ARRAY_SIZE(dm646x_dit_serializer_direction), | ||
310 | .tdm_slots = 32, | ||
311 | .serial_dir = dm646x_dit_serializer_direction, | ||
312 | .eventq_no = EVENTQ_0, | ||
313 | }, | ||
314 | }; | ||
315 | |||
316 | static struct i2c_client *cpld_client; | ||
317 | |||
318 | static int cpld_video_probe(struct i2c_client *client, | ||
319 | const struct i2c_device_id *id) | ||
320 | { | ||
321 | cpld_client = client; | ||
322 | return 0; | ||
323 | } | ||
324 | |||
325 | static int __devexit cpld_video_remove(struct i2c_client *client) | ||
326 | { | ||
327 | cpld_client = NULL; | ||
328 | return 0; | ||
329 | } | ||
330 | |||
331 | static const struct i2c_device_id cpld_video_id[] = { | ||
332 | { "cpld_video", 0 }, | ||
333 | { } | ||
334 | }; | ||
335 | |||
336 | static struct i2c_driver cpld_video_driver = { | ||
337 | .driver = { | ||
338 | .name = "cpld_video", | ||
339 | }, | ||
340 | .probe = cpld_video_probe, | ||
341 | .remove = cpld_video_remove, | ||
342 | .id_table = cpld_video_id, | ||
343 | }; | ||
344 | |||
345 | static void evm_init_cpld(void) | ||
346 | { | ||
347 | i2c_add_driver(&cpld_video_driver); | ||
348 | } | ||
349 | |||
209 | static struct i2c_board_info __initdata i2c_info[] = { | 350 | static struct i2c_board_info __initdata i2c_info[] = { |
210 | { | 351 | { |
211 | I2C_BOARD_INFO("24c256", 0x50), | 352 | I2C_BOARD_INFO("24c256", 0x50), |
@@ -215,6 +356,15 @@ static struct i2c_board_info __initdata i2c_info[] = { | |||
215 | I2C_BOARD_INFO("pcf8574a", 0x38), | 356 | I2C_BOARD_INFO("pcf8574a", 0x38), |
216 | .platform_data = &pcf_data, | 357 | .platform_data = &pcf_data, |
217 | }, | 358 | }, |
359 | { | ||
360 | I2C_BOARD_INFO("cpld_reg0", 0x3a), | ||
361 | }, | ||
362 | { | ||
363 | I2C_BOARD_INFO("tlv320aic33", 0x18), | ||
364 | }, | ||
365 | { | ||
366 | I2C_BOARD_INFO("cpld_video", 0x3b), | ||
367 | }, | ||
218 | }; | 368 | }; |
219 | 369 | ||
220 | static struct davinci_i2c_platform_data i2c_pdata = { | 370 | static struct davinci_i2c_platform_data i2c_pdata = { |
@@ -222,10 +372,265 @@ static struct davinci_i2c_platform_data i2c_pdata = { | |||
222 | .bus_delay = 0 /* usec */, | 372 | .bus_delay = 0 /* usec */, |
223 | }; | 373 | }; |
224 | 374 | ||
375 | static int set_vpif_clock(int mux_mode, int hd) | ||
376 | { | ||
377 | unsigned long flags; | ||
378 | unsigned int value; | ||
379 | int val = 0; | ||
380 | int err = 0; | ||
381 | |||
382 | if (!vpif_vidclkctl_reg || !vpif_vsclkdis_reg || !cpld_client) | ||
383 | return -ENXIO; | ||
384 | |||
385 | /* disable the clock */ | ||
386 | spin_lock_irqsave(&vpif_reg_lock, flags); | ||
387 | value = __raw_readl(vpif_vsclkdis_reg); | ||
388 | value |= (VIDCH3CLK | VIDCH2CLK); | ||
389 | __raw_writel(value, vpif_vsclkdis_reg); | ||
390 | spin_unlock_irqrestore(&vpif_reg_lock, flags); | ||
391 | |||
392 | val = i2c_smbus_read_byte(cpld_client); | ||
393 | if (val < 0) | ||
394 | return val; | ||
395 | |||
396 | if (mux_mode == 1) | ||
397 | val &= ~0x40; | ||
398 | else | ||
399 | val |= 0x40; | ||
400 | |||
401 | err = i2c_smbus_write_byte(cpld_client, val); | ||
402 | if (err) | ||
403 | return err; | ||
404 | |||
405 | value = __raw_readl(vpif_vidclkctl_reg); | ||
406 | value &= ~(VCH2CLK_MASK); | ||
407 | value &= ~(VCH3CLK_MASK); | ||
408 | |||
409 | if (hd >= 1) | ||
410 | value |= (VCH2CLK_SYSCLK8 | VCH3CLK_SYSCLK8); | ||
411 | else | ||
412 | value |= (VCH2CLK_AUXCLK | VCH3CLK_AUXCLK); | ||
413 | |||
414 | __raw_writel(value, vpif_vidclkctl_reg); | ||
415 | |||
416 | spin_lock_irqsave(&vpif_reg_lock, flags); | ||
417 | value = __raw_readl(vpif_vsclkdis_reg); | ||
418 | /* enable the clock */ | ||
419 | value &= ~(VIDCH3CLK | VIDCH2CLK); | ||
420 | __raw_writel(value, vpif_vsclkdis_reg); | ||
421 | spin_unlock_irqrestore(&vpif_reg_lock, flags); | ||
422 | |||
423 | return 0; | ||
424 | } | ||
425 | |||
426 | static struct vpif_subdev_info dm646x_vpif_subdev[] = { | ||
427 | { | ||
428 | .name = "adv7343", | ||
429 | .board_info = { | ||
430 | I2C_BOARD_INFO("adv7343", 0x2a), | ||
431 | }, | ||
432 | }, | ||
433 | { | ||
434 | .name = "ths7303", | ||
435 | .board_info = { | ||
436 | I2C_BOARD_INFO("ths7303", 0x2c), | ||
437 | }, | ||
438 | }, | ||
439 | }; | ||
440 | |||
441 | static const char *output[] = { | ||
442 | "Composite", | ||
443 | "Component", | ||
444 | "S-Video", | ||
445 | }; | ||
446 | |||
447 | static struct vpif_display_config dm646x_vpif_display_config = { | ||
448 | .set_clock = set_vpif_clock, | ||
449 | .subdevinfo = dm646x_vpif_subdev, | ||
450 | .subdev_count = ARRAY_SIZE(dm646x_vpif_subdev), | ||
451 | .output = output, | ||
452 | .output_count = ARRAY_SIZE(output), | ||
453 | .card_name = "DM646x EVM", | ||
454 | }; | ||
455 | |||
456 | /** | ||
457 | * setup_vpif_input_path() | ||
458 | * @channel: channel id (0 - CH0, 1 - CH1) | ||
459 | * @sub_dev_name: ptr sub device name | ||
460 | * | ||
461 | * This will set vpif input to capture data from tvp514x or | ||
462 | * tvp7002. | ||
463 | */ | ||
464 | static int setup_vpif_input_path(int channel, const char *sub_dev_name) | ||
465 | { | ||
466 | int err = 0; | ||
467 | int val; | ||
468 | |||
469 | /* for channel 1, we don't do anything */ | ||
470 | if (channel != 0) | ||
471 | return 0; | ||
472 | |||
473 | if (!cpld_client) | ||
474 | return -ENXIO; | ||
475 | |||
476 | val = i2c_smbus_read_byte(cpld_client); | ||
477 | if (val < 0) | ||
478 | return val; | ||
479 | |||
480 | if (!strcmp(sub_dev_name, TVP5147_CH0) || | ||
481 | !strcmp(sub_dev_name, TVP5147_CH1)) | ||
482 | val &= TVP5147_INPUT; | ||
483 | else | ||
484 | val |= TVP7002_INPUT; | ||
485 | |||
486 | err = i2c_smbus_write_byte(cpld_client, val); | ||
487 | if (err) | ||
488 | return err; | ||
489 | return 0; | ||
490 | } | ||
491 | |||
492 | /** | ||
493 | * setup_vpif_input_channel_mode() | ||
494 | * @mux_mode: mux mode. 0 - 1 channel or (1) - 2 channel | ||
495 | * | ||
496 | * This will setup input mode to one channel (TVP7002) or 2 channel (TVP5147) | ||
497 | */ | ||
498 | static int setup_vpif_input_channel_mode(int mux_mode) | ||
499 | { | ||
500 | unsigned long flags; | ||
501 | int err = 0; | ||
502 | int val; | ||
503 | u32 value; | ||
504 | |||
505 | if (!vpif_vsclkdis_reg || !cpld_client) | ||
506 | return -ENXIO; | ||
507 | |||
508 | val = i2c_smbus_read_byte(cpld_client); | ||
509 | if (val < 0) | ||
510 | return val; | ||
511 | |||
512 | spin_lock_irqsave(&vpif_reg_lock, flags); | ||
513 | value = __raw_readl(vpif_vsclkdis_reg); | ||
514 | if (mux_mode) { | ||
515 | val &= VPIF_INPUT_TWO_CHANNEL; | ||
516 | value |= VIDCH1CLK; | ||
517 | } else { | ||
518 | val |= VPIF_INPUT_ONE_CHANNEL; | ||
519 | value &= ~VIDCH1CLK; | ||
520 | } | ||
521 | __raw_writel(value, vpif_vsclkdis_reg); | ||
522 | spin_unlock_irqrestore(&vpif_reg_lock, flags); | ||
523 | |||
524 | err = i2c_smbus_write_byte(cpld_client, val); | ||
525 | if (err) | ||
526 | return err; | ||
527 | |||
528 | return 0; | ||
529 | } | ||
530 | |||
531 | static struct tvp514x_platform_data tvp5146_pdata = { | ||
532 | .clk_polarity = 0, | ||
533 | .hs_polarity = 1, | ||
534 | .vs_polarity = 1 | ||
535 | }; | ||
536 | |||
537 | #define TVP514X_STD_ALL (V4L2_STD_NTSC | V4L2_STD_PAL) | ||
538 | |||
539 | static struct vpif_subdev_info vpif_capture_sdev_info[] = { | ||
540 | { | ||
541 | .name = TVP5147_CH0, | ||
542 | .board_info = { | ||
543 | I2C_BOARD_INFO("tvp5146", 0x5d), | ||
544 | .platform_data = &tvp5146_pdata, | ||
545 | }, | ||
546 | .input = INPUT_CVBS_VI2B, | ||
547 | .output = OUTPUT_10BIT_422_EMBEDDED_SYNC, | ||
548 | .can_route = 1, | ||
549 | .vpif_if = { | ||
550 | .if_type = VPIF_IF_BT656, | ||
551 | .hd_pol = 1, | ||
552 | .vd_pol = 1, | ||
553 | .fid_pol = 0, | ||
554 | }, | ||
555 | }, | ||
556 | { | ||
557 | .name = TVP5147_CH1, | ||
558 | .board_info = { | ||
559 | I2C_BOARD_INFO("tvp5146", 0x5c), | ||
560 | .platform_data = &tvp5146_pdata, | ||
561 | }, | ||
562 | .input = INPUT_SVIDEO_VI2C_VI1C, | ||
563 | .output = OUTPUT_10BIT_422_EMBEDDED_SYNC, | ||
564 | .can_route = 1, | ||
565 | .vpif_if = { | ||
566 | .if_type = VPIF_IF_BT656, | ||
567 | .hd_pol = 1, | ||
568 | .vd_pol = 1, | ||
569 | .fid_pol = 0, | ||
570 | }, | ||
571 | }, | ||
572 | }; | ||
573 | |||
574 | static const struct vpif_input dm6467_ch0_inputs[] = { | ||
575 | { | ||
576 | .input = { | ||
577 | .index = 0, | ||
578 | .name = "Composite", | ||
579 | .type = V4L2_INPUT_TYPE_CAMERA, | ||
580 | .std = TVP514X_STD_ALL, | ||
581 | }, | ||
582 | .subdev_name = TVP5147_CH0, | ||
583 | }, | ||
584 | }; | ||
585 | |||
586 | static const struct vpif_input dm6467_ch1_inputs[] = { | ||
587 | { | ||
588 | .input = { | ||
589 | .index = 0, | ||
590 | .name = "S-Video", | ||
591 | .type = V4L2_INPUT_TYPE_CAMERA, | ||
592 | .std = TVP514X_STD_ALL, | ||
593 | }, | ||
594 | .subdev_name = TVP5147_CH1, | ||
595 | }, | ||
596 | }; | ||
597 | |||
598 | static struct vpif_capture_config dm646x_vpif_capture_cfg = { | ||
599 | .setup_input_path = setup_vpif_input_path, | ||
600 | .setup_input_channel_mode = setup_vpif_input_channel_mode, | ||
601 | .subdev_info = vpif_capture_sdev_info, | ||
602 | .subdev_count = ARRAY_SIZE(vpif_capture_sdev_info), | ||
603 | .chan_config[0] = { | ||
604 | .inputs = dm6467_ch0_inputs, | ||
605 | .input_count = ARRAY_SIZE(dm6467_ch0_inputs), | ||
606 | }, | ||
607 | .chan_config[1] = { | ||
608 | .inputs = dm6467_ch1_inputs, | ||
609 | .input_count = ARRAY_SIZE(dm6467_ch1_inputs), | ||
610 | }, | ||
611 | }; | ||
612 | |||
613 | static void __init evm_init_video(void) | ||
614 | { | ||
615 | vpif_vidclkctl_reg = ioremap(VIDCLKCTL_OFFSET, 4); | ||
616 | vpif_vsclkdis_reg = ioremap(VSCLKDIS_OFFSET, 4); | ||
617 | if (!vpif_vidclkctl_reg || !vpif_vsclkdis_reg) { | ||
618 | pr_err("Can't map VPIF VIDCLKCTL or VSCLKDIS registers\n"); | ||
619 | return; | ||
620 | } | ||
621 | spin_lock_init(&vpif_reg_lock); | ||
622 | |||
623 | dm646x_setup_vpif(&dm646x_vpif_display_config, | ||
624 | &dm646x_vpif_capture_cfg); | ||
625 | } | ||
626 | |||
225 | static void __init evm_init_i2c(void) | 627 | static void __init evm_init_i2c(void) |
226 | { | 628 | { |
227 | davinci_init_i2c(&i2c_pdata); | 629 | davinci_init_i2c(&i2c_pdata); |
630 | i2c_add_driver(&dm6467evm_cpld_driver); | ||
228 | i2c_register_board_info(1, i2c_info, ARRAY_SIZE(i2c_info)); | 631 | i2c_register_board_info(1, i2c_info, ARRAY_SIZE(i2c_info)); |
632 | evm_init_cpld(); | ||
633 | evm_init_video(); | ||
229 | } | 634 | } |
230 | 635 | ||
231 | static void __init davinci_map_io(void) | 636 | static void __init davinci_map_io(void) |
@@ -239,6 +644,11 @@ static __init void evm_init(void) | |||
239 | 644 | ||
240 | evm_init_i2c(); | 645 | evm_init_i2c(); |
241 | davinci_serial_init(&uart_config); | 646 | davinci_serial_init(&uart_config); |
647 | dm646x_init_mcasp0(&dm646x_evm_snd_data[0]); | ||
648 | dm646x_init_mcasp1(&dm646x_evm_snd_data[1]); | ||
649 | |||
650 | if (HAS_ATA) | ||
651 | dm646x_init_ide(); | ||
242 | 652 | ||
243 | soc_info->emac_pdata->phy_mask = DM646X_EVM_PHY_MASK; | 653 | soc_info->emac_pdata->phy_mask = DM646X_EVM_PHY_MASK; |
244 | soc_info->emac_pdata->mdio_max_freq = DM646X_EVM_MDIO_FREQUENCY; | 654 | soc_info->emac_pdata->mdio_max_freq = DM646X_EVM_MDIO_FREQUENCY; |