Path: blob/master/drivers/media/video/davinci/vpif.c
17628 views
/*1* vpif - DM646x Video Port Interface driver2* VPIF is a receiver and transmitter for video data. It has two channels(0, 1)3* that receiveing video byte stream and two channels(2, 3) for video output.4* The hardware supports SDTV, HDTV formats, raw data capture.5* Currently, the driver supports NTSC and PAL standards.6*7* Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/8*9* This program is free software; you can redistribute it and/or10* modify it under the terms of the GNU General Public License as11* published by the Free Software Foundation version 2.12*13* This program is distributed .as is. WITHOUT ANY WARRANTY of any14* kind, whether express or implied; without even the implied warranty15* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the16* GNU General Public License for more details.17*/1819#include <linux/init.h>20#include <linux/module.h>21#include <linux/platform_device.h>22#include <linux/spinlock.h>23#include <linux/kernel.h>24#include <linux/io.h>25#include <mach/hardware.h>2627#include "vpif.h"2829MODULE_DESCRIPTION("TI DaVinci Video Port Interface driver");30MODULE_LICENSE("GPL");3132#define VPIF_CH0_MAX_MODES (22)33#define VPIF_CH1_MAX_MODES (02)34#define VPIF_CH2_MAX_MODES (15)35#define VPIF_CH3_MAX_MODES (02)3637static resource_size_t res_len;38static struct resource *res;39spinlock_t vpif_lock;4041void __iomem *vpif_base;4243/**44* ch_params: video standard configuration parameters for vpif45* The table must include all presets from supported subdevices.46*/47const struct vpif_channel_config_params ch_params[] = {48/* HDTV formats */49{50.name = "480p59_94",51.width = 720,52.height = 480,53.frm_fmt = 1,54.ycmux_mode = 0,55.eav2sav = 138-8,56.sav2eav = 720,57.l1 = 1,58.l3 = 43,59.l5 = 523,60.vsize = 525,61.capture_format = 0,62.vbi_supported = 0,63.hd_sd = 1,64.dv_preset = V4L2_DV_480P59_94,65},66{67.name = "576p50",68.width = 720,69.height = 576,70.frm_fmt = 1,71.ycmux_mode = 0,72.eav2sav = 144-8,73.sav2eav = 720,74.l1 = 1,75.l3 = 45,76.l5 = 621,77.vsize = 625,78.capture_format = 0,79.vbi_supported = 0,80.hd_sd = 1,81.dv_preset = V4L2_DV_576P50,82},83{84.name = "720p50",85.width = 1280,86.height = 720,87.frm_fmt = 1,88.ycmux_mode = 0,89.eav2sav = 700-8,90.sav2eav = 1280,91.l1 = 1,92.l3 = 26,93.l5 = 746,94.vsize = 750,95.capture_format = 0,96.vbi_supported = 0,97.hd_sd = 1,98.dv_preset = V4L2_DV_720P50,99},100{101.name = "720p60",102.width = 1280,103.height = 720,104.frm_fmt = 1,105.ycmux_mode = 0,106.eav2sav = 370 - 8,107.sav2eav = 1280,108.l1 = 1,109.l3 = 26,110.l5 = 746,111.vsize = 750,112.capture_format = 0,113.vbi_supported = 0,114.hd_sd = 1,115.dv_preset = V4L2_DV_720P60,116},117{118.name = "1080I50",119.width = 1920,120.height = 1080,121.frm_fmt = 0,122.ycmux_mode = 0,123.eav2sav = 720 - 8,124.sav2eav = 1920,125.l1 = 1,126.l3 = 21,127.l5 = 561,128.l7 = 563,129.l9 = 584,130.l11 = 1124,131.vsize = 1125,132.capture_format = 0,133.vbi_supported = 0,134.hd_sd = 1,135.dv_preset = V4L2_DV_1080I50,136},137{138.name = "1080I60",139.width = 1920,140.height = 1080,141.frm_fmt = 0,142.ycmux_mode = 0,143.eav2sav = 280 - 8,144.sav2eav = 1920,145.l1 = 1,146.l3 = 21,147.l5 = 561,148.l7 = 563,149.l9 = 584,150.l11 = 1124,151.vsize = 1125,152.capture_format = 0,153.vbi_supported = 0,154.hd_sd = 1,155.dv_preset = V4L2_DV_1080I60,156},157{158.name = "1080p60",159.width = 1920,160.height = 1080,161.frm_fmt = 1,162.ycmux_mode = 0,163.eav2sav = 280 - 8,164.sav2eav = 1920,165.l1 = 1,166.l3 = 42,167.l5 = 1122,168.vsize = 1125,169.capture_format = 0,170.vbi_supported = 0,171.hd_sd = 1,172.dv_preset = V4L2_DV_1080P60,173},174175/* SDTV formats */176{177.name = "NTSC_M",178.width = 720,179.height = 480,180.frm_fmt = 0,181.ycmux_mode = 1,182.eav2sav = 268,183.sav2eav = 1440,184.l1 = 1,185.l3 = 23,186.l5 = 263,187.l7 = 266,188.l9 = 286,189.l11 = 525,190.vsize = 525,191.capture_format = 0,192.vbi_supported = 1,193.hd_sd = 0,194.stdid = V4L2_STD_525_60,195},196{197.name = "PAL_BDGHIK",198.width = 720,199.height = 576,200.frm_fmt = 0,201.ycmux_mode = 1,202.eav2sav = 280,203.sav2eav = 1440,204.l1 = 1,205.l3 = 23,206.l5 = 311,207.l7 = 313,208.l9 = 336,209.l11 = 624,210.vsize = 625,211.capture_format = 0,212.vbi_supported = 1,213.hd_sd = 0,214.stdid = V4L2_STD_625_50,215},216};217218const unsigned int vpif_ch_params_count = ARRAY_SIZE(ch_params);219220static inline void vpif_wr_bit(u32 reg, u32 bit, u32 val)221{222if (val)223vpif_set_bit(reg, bit);224else225vpif_clr_bit(reg, bit);226}227228/* This structure is used to keep track of VPIF size register's offsets */229struct vpif_registers {230u32 h_cfg, v_cfg_00, v_cfg_01, v_cfg_02, v_cfg, ch_ctrl;231u32 line_offset, vanc0_strt, vanc0_size, vanc1_strt;232u32 vanc1_size, width_mask, len_mask;233u8 max_modes;234};235236static const struct vpif_registers vpifregs[VPIF_NUM_CHANNELS] = {237/* Channel0 */238{239VPIF_CH0_H_CFG, VPIF_CH0_V_CFG_00, VPIF_CH0_V_CFG_01,240VPIF_CH0_V_CFG_02, VPIF_CH0_V_CFG_03, VPIF_CH0_CTRL,241VPIF_CH0_IMG_ADD_OFST, 0, 0, 0, 0, 0x1FFF, 0xFFF,242VPIF_CH0_MAX_MODES,243},244/* Channel1 */245{246VPIF_CH1_H_CFG, VPIF_CH1_V_CFG_00, VPIF_CH1_V_CFG_01,247VPIF_CH1_V_CFG_02, VPIF_CH1_V_CFG_03, VPIF_CH1_CTRL,248VPIF_CH1_IMG_ADD_OFST, 0, 0, 0, 0, 0x1FFF, 0xFFF,249VPIF_CH1_MAX_MODES,250},251/* Channel2 */252{253VPIF_CH2_H_CFG, VPIF_CH2_V_CFG_00, VPIF_CH2_V_CFG_01,254VPIF_CH2_V_CFG_02, VPIF_CH2_V_CFG_03, VPIF_CH2_CTRL,255VPIF_CH2_IMG_ADD_OFST, VPIF_CH2_VANC0_STRT, VPIF_CH2_VANC0_SIZE,256VPIF_CH2_VANC1_STRT, VPIF_CH2_VANC1_SIZE, 0x7FF, 0x7FF,257VPIF_CH2_MAX_MODES258},259/* Channel3 */260{261VPIF_CH3_H_CFG, VPIF_CH3_V_CFG_00, VPIF_CH3_V_CFG_01,262VPIF_CH3_V_CFG_02, VPIF_CH3_V_CFG_03, VPIF_CH3_CTRL,263VPIF_CH3_IMG_ADD_OFST, VPIF_CH3_VANC0_STRT, VPIF_CH3_VANC0_SIZE,264VPIF_CH3_VANC1_STRT, VPIF_CH3_VANC1_SIZE, 0x7FF, 0x7FF,265VPIF_CH3_MAX_MODES266},267};268269/* vpif_set_mode_info:270* This function is used to set horizontal and vertical config parameters271* As per the standard in the channel, configure the values of L1, L3,272* L5, L7 L9, L11 in VPIF Register , also write width and height273*/274static void vpif_set_mode_info(const struct vpif_channel_config_params *config,275u8 channel_id, u8 config_channel_id)276{277u32 value;278279value = (config->eav2sav & vpifregs[config_channel_id].width_mask);280value <<= VPIF_CH_LEN_SHIFT;281value |= (config->sav2eav & vpifregs[config_channel_id].width_mask);282regw(value, vpifregs[channel_id].h_cfg);283284value = (config->l1 & vpifregs[config_channel_id].len_mask);285value <<= VPIF_CH_LEN_SHIFT;286value |= (config->l3 & vpifregs[config_channel_id].len_mask);287regw(value, vpifregs[channel_id].v_cfg_00);288289value = (config->l5 & vpifregs[config_channel_id].len_mask);290value <<= VPIF_CH_LEN_SHIFT;291value |= (config->l7 & vpifregs[config_channel_id].len_mask);292regw(value, vpifregs[channel_id].v_cfg_01);293294value = (config->l9 & vpifregs[config_channel_id].len_mask);295value <<= VPIF_CH_LEN_SHIFT;296value |= (config->l11 & vpifregs[config_channel_id].len_mask);297regw(value, vpifregs[channel_id].v_cfg_02);298299value = (config->vsize & vpifregs[config_channel_id].len_mask);300regw(value, vpifregs[channel_id].v_cfg);301}302303/* config_vpif_params304* Function to set the parameters of a channel305* Mainly modifies the channel ciontrol register306* It sets frame format, yc mux mode307*/308static void config_vpif_params(struct vpif_params *vpifparams,309u8 channel_id, u8 found)310{311const struct vpif_channel_config_params *config = &vpifparams->std_info;312u32 value, ch_nip, reg;313u8 start, end;314int i;315316start = channel_id;317end = channel_id + found;318319for (i = start; i < end; i++) {320reg = vpifregs[i].ch_ctrl;321if (channel_id < 2)322ch_nip = VPIF_CAPTURE_CH_NIP;323else324ch_nip = VPIF_DISPLAY_CH_NIP;325326vpif_wr_bit(reg, ch_nip, config->frm_fmt);327vpif_wr_bit(reg, VPIF_CH_YC_MUX_BIT, config->ycmux_mode);328vpif_wr_bit(reg, VPIF_CH_INPUT_FIELD_FRAME_BIT,329vpifparams->video_params.storage_mode);330331/* Set raster scanning SDR Format */332vpif_clr_bit(reg, VPIF_CH_SDR_FMT_BIT);333vpif_wr_bit(reg, VPIF_CH_DATA_MODE_BIT, config->capture_format);334335if (channel_id > 1) /* Set the Pixel enable bit */336vpif_set_bit(reg, VPIF_DISPLAY_PIX_EN_BIT);337else if (config->capture_format) {338/* Set the polarity of various pins */339vpif_wr_bit(reg, VPIF_CH_FID_POLARITY_BIT,340vpifparams->iface.fid_pol);341vpif_wr_bit(reg, VPIF_CH_V_VALID_POLARITY_BIT,342vpifparams->iface.vd_pol);343vpif_wr_bit(reg, VPIF_CH_H_VALID_POLARITY_BIT,344vpifparams->iface.hd_pol);345346value = regr(reg);347/* Set data width */348value &= ((~(unsigned int)(0x3)) <<349VPIF_CH_DATA_WIDTH_BIT);350value |= ((vpifparams->params.data_sz) <<351VPIF_CH_DATA_WIDTH_BIT);352regw(value, reg);353}354355/* Write the pitch in the driver */356regw((vpifparams->video_params.hpitch),357vpifregs[i].line_offset);358}359}360361/* vpif_set_video_params362* This function is used to set video parameters in VPIF register363*/364int vpif_set_video_params(struct vpif_params *vpifparams, u8 channel_id)365{366const struct vpif_channel_config_params *config = &vpifparams->std_info;367int found = 1;368369vpif_set_mode_info(config, channel_id, channel_id);370if (!config->ycmux_mode) {371/* YC are on separate channels (HDTV formats) */372vpif_set_mode_info(config, channel_id + 1, channel_id);373found = 2;374}375376config_vpif_params(vpifparams, channel_id, found);377378regw(0x80, VPIF_REQ_SIZE);379regw(0x01, VPIF_EMULATION_CTRL);380381return found;382}383EXPORT_SYMBOL(vpif_set_video_params);384385void vpif_set_vbi_display_params(struct vpif_vbi_params *vbiparams,386u8 channel_id)387{388u32 value;389390value = 0x3F8 & (vbiparams->hstart0);391value |= 0x3FFFFFF & ((vbiparams->vstart0) << 16);392regw(value, vpifregs[channel_id].vanc0_strt);393394value = 0x3F8 & (vbiparams->hstart1);395value |= 0x3FFFFFF & ((vbiparams->vstart1) << 16);396regw(value, vpifregs[channel_id].vanc1_strt);397398value = 0x3F8 & (vbiparams->hsize0);399value |= 0x3FFFFFF & ((vbiparams->vsize0) << 16);400regw(value, vpifregs[channel_id].vanc0_size);401402value = 0x3F8 & (vbiparams->hsize1);403value |= 0x3FFFFFF & ((vbiparams->vsize1) << 16);404regw(value, vpifregs[channel_id].vanc1_size);405406}407EXPORT_SYMBOL(vpif_set_vbi_display_params);408409int vpif_channel_getfid(u8 channel_id)410{411return (regr(vpifregs[channel_id].ch_ctrl) & VPIF_CH_FID_MASK)412>> VPIF_CH_FID_SHIFT;413}414EXPORT_SYMBOL(vpif_channel_getfid);415416static int __init vpif_probe(struct platform_device *pdev)417{418int status = 0;419420res = platform_get_resource(pdev, IORESOURCE_MEM, 0);421if (!res)422return -ENOENT;423424res_len = res->end - res->start + 1;425426res = request_mem_region(res->start, res_len, res->name);427if (!res)428return -EBUSY;429430vpif_base = ioremap(res->start, res_len);431if (!vpif_base) {432status = -EBUSY;433goto fail;434}435436spin_lock_init(&vpif_lock);437dev_info(&pdev->dev, "vpif probe success\n");438return 0;439440fail:441release_mem_region(res->start, res_len);442return status;443}444445static int __devexit vpif_remove(struct platform_device *pdev)446{447iounmap(vpif_base);448release_mem_region(res->start, res_len);449return 0;450}451452static struct platform_driver vpif_driver = {453.driver = {454.name = "vpif",455.owner = THIS_MODULE,456},457.remove = __devexit_p(vpif_remove),458.probe = vpif_probe,459};460461static void vpif_exit(void)462{463platform_driver_unregister(&vpif_driver);464}465466static int __init vpif_init(void)467{468return platform_driver_register(&vpif_driver);469}470subsys_initcall(vpif_init);471module_exit(vpif_exit);472473474475