Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 85609c1c authored by Muralidharan Karicheri's avatar Muralidharan Karicheri Committed by Kevin Hilman
Browse files

DaVinci: DM646x - platform changes for vpif capture and display drivers



VPIF display changes (Chaithrika)

Add platform device and resource structures. Also define a platform specific
clock setup function that can be accessed by the driver to configure the clock
and CPLD.

VPIF caputure changes (Murali)

1) Modify vpif_subdev_info to add board_info, routing information and
   vpif interface configuration. Remove addr since it is part of
   board_info

2) Add code to setup channel mode and input decoder path for vpif
   capture driver

Also incorporated comments against version v0 of the patch series and
added a spinlock to protect writes to common registers

Tested on DM6467 on channel 0 using TVP514x. Following bootargs used
for drivers:

   vpif_capture.ch0_bufsize=829440 vpif_display.ch2_bufsize=829440

Signed-off-by: default avatarManjunath Hadli <mrh@ti.com>
Signed-off-by: default avatarBrijesh Jadav <brijesh.j@ti.com>
Signed-off-by: default avatarChaithrika U S <chaithrika@ti.com>
Reviewed-by: default avatarHans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: default avatarMuralidharan Karicheri <m-karicheri2@ti.com>
Signed-off-by: default avatarKevin Hilman <khilman@deeprootsystems.com>
parent 51e68e27
Loading
Loading
Loading
Loading
+318 −1
Original line number Diff line number Diff line
@@ -34,6 +34,8 @@
#include <linux/i2c/pcf857x.h>
#include <linux/etherdevice.h>

#include <media/tvp514x.h>

#include <asm/setup.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
@@ -62,6 +64,30 @@
#define DM646X_EVM_PHY_MASK		(0x2)
#define DM646X_EVM_MDIO_FREQUENCY	(2200000) /* PHY bus frequency */

#define VIDCLKCTL_OFFSET	(DAVINCI_SYSTEM_MODULE_BASE + 0x38)
#define VSCLKDIS_OFFSET		(DAVINCI_SYSTEM_MODULE_BASE + 0x6c)
#define VCH2CLK_MASK		(BIT_MASK(10) | BIT_MASK(9) | BIT_MASK(8))
#define VCH2CLK_SYSCLK8		(BIT(9))
#define VCH2CLK_AUXCLK		(BIT(9) | BIT(8))
#define VCH3CLK_MASK		(BIT_MASK(14) | BIT_MASK(13) | BIT_MASK(12))
#define VCH3CLK_SYSCLK8		(BIT(13))
#define VCH3CLK_AUXCLK		(BIT(14) | BIT(13))

#define VIDCH2CLK		(BIT(10))
#define VIDCH3CLK		(BIT(11))
#define VIDCH1CLK		(BIT(4))
#define TVP7002_INPUT		(BIT(4))
#define TVP5147_INPUT		(~BIT(4))
#define VPIF_INPUT_ONE_CHANNEL	(BIT(5))
#define VPIF_INPUT_TWO_CHANNEL	(~BIT(5))
#define TVP5147_CH0		"tvp514x-0"
#define TVP5147_CH1		"tvp514x-1"

static void __iomem *vpif_vidclkctl_reg;
static void __iomem *vpif_vsclkdis_reg;
/* spin lock for updating above registers */
static spinlock_t vpif_reg_lock;

static struct davinci_uart_config uart_config __initdata = {
	.enabled_uarts = (1 << 0),
};
@@ -287,6 +313,40 @@ static struct snd_platform_data dm646x_evm_snd_data[] = {
	},
};

static struct i2c_client *cpld_client;

static int cpld_video_probe(struct i2c_client *client,
			const struct i2c_device_id *id)
{
	cpld_client = client;
	return 0;
}

static int __devexit cpld_video_remove(struct i2c_client *client)
{
	cpld_client = NULL;
	return 0;
}

static const struct i2c_device_id cpld_video_id[] = {
	{ "cpld_video", 0 },
	{ }
};

static struct i2c_driver cpld_video_driver = {
	.driver = {
		.name	= "cpld_video",
	},
	.probe		= cpld_video_probe,
	.remove		= cpld_video_remove,
	.id_table	= cpld_video_id,
};

static void evm_init_cpld(void)
{
	i2c_add_driver(&cpld_video_driver);
}

static struct i2c_board_info __initdata i2c_info[] =  {
	{
		I2C_BOARD_INFO("24c256", 0x50),
@@ -301,7 +361,10 @@ static struct i2c_board_info __initdata i2c_info[] = {
	},
	{
		I2C_BOARD_INFO("tlv320aic33", 0x18),
	}
	},
	{
		I2C_BOARD_INFO("cpld_video", 0x3b),
	},
};

static struct davinci_i2c_platform_data i2c_pdata = {
@@ -309,11 +372,265 @@ static struct davinci_i2c_platform_data i2c_pdata = {
	.bus_delay      = 0 /* usec */,
};

static int set_vpif_clock(int mux_mode, int hd)
{
	unsigned long flags;
	unsigned int value;
	int val = 0;
	int err = 0;

	if (!vpif_vidclkctl_reg || !vpif_vsclkdis_reg || !cpld_client)
		return -ENXIO;

	/* disable the clock */
	spin_lock_irqsave(&vpif_reg_lock, flags);
	value = __raw_readl(vpif_vsclkdis_reg);
	value |= (VIDCH3CLK | VIDCH2CLK);
	__raw_writel(value, vpif_vsclkdis_reg);
	spin_unlock_irqrestore(&vpif_reg_lock, flags);

	val = i2c_smbus_read_byte(cpld_client);
	if (val < 0)
		return val;

	if (mux_mode == 1)
		val &= ~0x40;
	else
		val |= 0x40;

	err = i2c_smbus_write_byte(cpld_client, val);
	if (err)
		return err;

	value = __raw_readl(vpif_vidclkctl_reg);
	value &= ~(VCH2CLK_MASK);
	value &= ~(VCH3CLK_MASK);

	if (hd >= 1)
		value |= (VCH2CLK_SYSCLK8 | VCH3CLK_SYSCLK8);
	else
		value |= (VCH2CLK_AUXCLK | VCH3CLK_AUXCLK);

	__raw_writel(value, vpif_vidclkctl_reg);

	spin_lock_irqsave(&vpif_reg_lock, flags);
	value = __raw_readl(vpif_vsclkdis_reg);
	/* enable the clock */
	value &= ~(VIDCH3CLK | VIDCH2CLK);
	__raw_writel(value, vpif_vsclkdis_reg);
	spin_unlock_irqrestore(&vpif_reg_lock, flags);

	return 0;
}

static struct vpif_subdev_info dm646x_vpif_subdev[] = {
	{
		.name	= "adv7343",
		.board_info = {
			I2C_BOARD_INFO("adv7343", 0x2a),
		},
	},
	{
		.name	= "ths7303",
		.board_info = {
			I2C_BOARD_INFO("ths7303", 0x2c),
		},
	},
};

static const char *output[] = {
	"Composite",
	"Component",
	"S-Video",
};

static struct vpif_display_config dm646x_vpif_display_config = {
	.set_clock	= set_vpif_clock,
	.subdevinfo	= dm646x_vpif_subdev,
	.subdev_count	= ARRAY_SIZE(dm646x_vpif_subdev),
	.output		= output,
	.output_count	= ARRAY_SIZE(output),
	.card_name	= "DM646x EVM",
};

/**
 * setup_vpif_input_path()
 * @channel: channel id (0 - CH0, 1 - CH1)
 * @sub_dev_name: ptr sub device name
 *
 * This will set vpif input to capture data from tvp514x or
 * tvp7002.
 */
static int setup_vpif_input_path(int channel, const char *sub_dev_name)
{
	int err = 0;
	int val;

	/* for channel 1, we don't do anything */
	if (channel != 0)
		return 0;

	if (!cpld_client)
		return -ENXIO;

	val = i2c_smbus_read_byte(cpld_client);
	if (val < 0)
		return val;

	if (!strcmp(sub_dev_name, TVP5147_CH0) ||
	    !strcmp(sub_dev_name, TVP5147_CH1))
		val &= TVP5147_INPUT;
	else
		val |= TVP7002_INPUT;

	err = i2c_smbus_write_byte(cpld_client, val);
	if (err)
		return err;
	return 0;
}

/**
 * setup_vpif_input_channel_mode()
 * @mux_mode:  mux mode. 0 - 1 channel or (1) - 2 channel
 *
 * This will setup input mode to one channel (TVP7002) or 2 channel (TVP5147)
 */
static int setup_vpif_input_channel_mode(int mux_mode)
{
	unsigned long flags;
	int err = 0;
	int val;
	u32 value;

	if (!vpif_vsclkdis_reg || !cpld_client)
		return -ENXIO;

	val = i2c_smbus_read_byte(cpld_client);
	if (val < 0)
		return val;

	spin_lock_irqsave(&vpif_reg_lock, flags);
	value = __raw_readl(vpif_vsclkdis_reg);
	if (mux_mode) {
		val &= VPIF_INPUT_TWO_CHANNEL;
		value |= VIDCH1CLK;
	} else {
		val |= VPIF_INPUT_ONE_CHANNEL;
		value &= ~VIDCH1CLK;
	}
	__raw_writel(value, vpif_vsclkdis_reg);
	spin_unlock_irqrestore(&vpif_reg_lock, flags);

	err = i2c_smbus_write_byte(cpld_client, val);
	if (err)
		return err;

	return 0;
}

static struct tvp514x_platform_data tvp5146_pdata = {
	.clk_polarity = 0,
	.hs_polarity = 1,
	.vs_polarity = 1
};

#define TVP514X_STD_ALL (V4L2_STD_NTSC | V4L2_STD_PAL)

static struct vpif_subdev_info vpif_capture_sdev_info[] = {
	{
		.name	= TVP5147_CH0,
		.board_info = {
			I2C_BOARD_INFO("tvp5146", 0x5d),
			.platform_data = &tvp5146_pdata,
		},
		.input = INPUT_CVBS_VI2B,
		.output = OUTPUT_10BIT_422_EMBEDDED_SYNC,
		.can_route = 1,
		.vpif_if = {
			.if_type = VPIF_IF_BT656,
			.hd_pol = 1,
			.vd_pol = 1,
			.fid_pol = 0,
		},
	},
	{
		.name	= TVP5147_CH1,
		.board_info = {
			I2C_BOARD_INFO("tvp5146", 0x5c),
			.platform_data = &tvp5146_pdata,
		},
		.input = INPUT_SVIDEO_VI2C_VI1C,
		.output = OUTPUT_10BIT_422_EMBEDDED_SYNC,
		.can_route = 1,
		.vpif_if = {
			.if_type = VPIF_IF_BT656,
			.hd_pol = 1,
			.vd_pol = 1,
			.fid_pol = 0,
		},
	},
};

static const struct vpif_input dm6467_ch0_inputs[] = {
	{
		.input = {
			.index = 0,
			.name = "Composite",
			.type = V4L2_INPUT_TYPE_CAMERA,
			.std = TVP514X_STD_ALL,
		},
		.subdev_name = TVP5147_CH0,
	},
};

static const struct vpif_input dm6467_ch1_inputs[] = {
       {
		.input = {
			.index = 0,
			.name = "S-Video",
			.type = V4L2_INPUT_TYPE_CAMERA,
			.std = TVP514X_STD_ALL,
		},
		.subdev_name = TVP5147_CH1,
	},
};

static struct vpif_capture_config dm646x_vpif_capture_cfg = {
	.setup_input_path = setup_vpif_input_path,
	.setup_input_channel_mode = setup_vpif_input_channel_mode,
	.subdev_info = vpif_capture_sdev_info,
	.subdev_count = ARRAY_SIZE(vpif_capture_sdev_info),
	.chan_config[0] = {
		.inputs = dm6467_ch0_inputs,
		.input_count = ARRAY_SIZE(dm6467_ch0_inputs),
	},
	.chan_config[1] = {
		.inputs = dm6467_ch1_inputs,
		.input_count = ARRAY_SIZE(dm6467_ch1_inputs),
	},
};

static void __init evm_init_video(void)
{
	vpif_vidclkctl_reg = ioremap(VIDCLKCTL_OFFSET, 4);
	vpif_vsclkdis_reg = ioremap(VSCLKDIS_OFFSET, 4);
	if (!vpif_vidclkctl_reg || !vpif_vsclkdis_reg) {
		pr_err("Can't map VPIF VIDCLKCTL or VSCLKDIS registers\n");
		return;
	}
	spin_lock_init(&vpif_reg_lock);

	dm646x_setup_vpif(&dm646x_vpif_display_config,
			  &dm646x_vpif_capture_cfg);
}

static void __init evm_init_i2c(void)
{
	davinci_init_i2c(&i2c_pdata);
	i2c_add_driver(&dm6467evm_cpld_driver);
	i2c_register_board_info(1, i2c_info, ARRAY_SIZE(i2c_info));
	evm_init_cpld();
	evm_init_video();
}

static void __init davinci_map_io(void)
+104 −0
Original line number Diff line number Diff line
@@ -32,6 +32,15 @@
#include "clock.h"
#include "mux.h"

#define DAVINCI_VPIF_BASE       (0x01C12000)
#define VDD3P3V_PWDN_OFFSET	(0x48)
#define VSCLKDIS_OFFSET		(0x6C)

#define VDD3P3V_VID_MASK	(BIT_MASK(3) | BIT_MASK(2) | BIT_MASK(1) |\
					BIT_MASK(0))
#define VSCLKDIS_MASK		(BIT_MASK(11) | BIT_MASK(10) | BIT_MASK(9) |\
					BIT_MASK(8))

/*
 * Device specific clocks
 */
@@ -686,6 +695,75 @@ static struct platform_device dm646x_dit_device = {
	.id	= -1,
};

static u64 vpif_dma_mask = DMA_BIT_MASK(32);

static struct resource vpif_resource[] = {
	{
		.start	= DAVINCI_VPIF_BASE,
		.end	= DAVINCI_VPIF_BASE + 0x03ff,
		.flags	= IORESOURCE_MEM,
	}
};

static struct platform_device vpif_dev = {
	.name		= "vpif",
	.id		= -1,
	.dev		= {
			.dma_mask 		= &vpif_dma_mask,
			.coherent_dma_mask	= DMA_BIT_MASK(32),
	},
	.resource	= vpif_resource,
	.num_resources	= ARRAY_SIZE(vpif_resource),
};

static struct resource vpif_display_resource[] = {
	{
		.start = IRQ_DM646X_VP_VERTINT2,
		.end   = IRQ_DM646X_VP_VERTINT2,
		.flags = IORESOURCE_IRQ,
	},
	{
		.start = IRQ_DM646X_VP_VERTINT3,
		.end   = IRQ_DM646X_VP_VERTINT3,
		.flags = IORESOURCE_IRQ,
	},
};

static struct platform_device vpif_display_dev = {
	.name		= "vpif_display",
	.id		= -1,
	.dev		= {
			.dma_mask 		= &vpif_dma_mask,
			.coherent_dma_mask	= DMA_BIT_MASK(32),
	},
	.resource	= vpif_display_resource,
	.num_resources	= ARRAY_SIZE(vpif_display_resource),
};

static struct resource vpif_capture_resource[] = {
	{
		.start = IRQ_DM646X_VP_VERTINT0,
		.end   = IRQ_DM646X_VP_VERTINT0,
		.flags = IORESOURCE_IRQ,
	},
	{
		.start = IRQ_DM646X_VP_VERTINT1,
		.end   = IRQ_DM646X_VP_VERTINT1,
		.flags = IORESOURCE_IRQ,
	},
};

static struct platform_device vpif_capture_dev = {
	.name		= "vpif_capture",
	.id		= -1,
	.dev		= {
			.dma_mask 		= &vpif_dma_mask,
			.coherent_dma_mask	= DMA_BIT_MASK(32),
	},
	.resource	= vpif_capture_resource,
	.num_resources	= ARRAY_SIZE(vpif_capture_resource),
};

/*----------------------------------------------------------------------*/

static struct map_desc dm646x_io_desc[] = {
@@ -814,6 +892,32 @@ void __init dm646x_init_mcasp1(struct snd_platform_data *pdata)
	platform_device_register(&dm646x_dit_device);
}

void dm646x_setup_vpif(struct vpif_display_config *display_config,
		       struct vpif_capture_config *capture_config)
{
	unsigned int value;
	void __iomem *base = IO_ADDRESS(DAVINCI_SYSTEM_MODULE_BASE);

	value = __raw_readl(base + VSCLKDIS_OFFSET);
	value &= ~VSCLKDIS_MASK;
	__raw_writel(value, base + VSCLKDIS_OFFSET);

	value = __raw_readl(base + VDD3P3V_PWDN_OFFSET);
	value &= ~VDD3P3V_VID_MASK;
	__raw_writel(value, base + VDD3P3V_PWDN_OFFSET);

	davinci_cfg_reg(DM646X_STSOMUX_DISABLE);
	davinci_cfg_reg(DM646X_STSIMUX_DISABLE);
	davinci_cfg_reg(DM646X_PTSOMUX_DISABLE);
	davinci_cfg_reg(DM646X_PTSIMUX_DISABLE);

	vpif_display_dev.dev.platform_data = display_config;
	vpif_capture_dev.dev.platform_data = capture_config;
	platform_device_register(&vpif_dev);
	platform_device_register(&vpif_display_dev);
	platform_device_register(&vpif_capture_dev);
}

void __init dm646x_init(void)
{
	davinci_common_init(&davinci_soc_info_dm646x);
+59 −0
Original line number Diff line number Diff line
@@ -14,6 +14,8 @@
#include <mach/hardware.h>
#include <mach/emac.h>
#include <mach/asp.h>
#include <linux/i2c.h>
#include <linux/videodev2.h>

#define DM646X_EMAC_BASE		(0x01C80000)
#define DM646X_EMAC_CNTRL_OFFSET	(0x0000)
@@ -29,4 +31,61 @@ void __init dm646x_init_ide(void);
void __init dm646x_init_mcasp0(struct snd_platform_data *pdata);
void __init dm646x_init_mcasp1(struct snd_platform_data *pdata);

void dm646x_video_init(void);

enum vpif_if_type {
	VPIF_IF_BT656,
	VPIF_IF_BT1120,
	VPIF_IF_RAW_BAYER
};

struct vpif_interface {
	enum vpif_if_type if_type;
	unsigned hd_pol:1;
	unsigned vd_pol:1;
	unsigned fid_pol:1;
};

struct vpif_subdev_info {
	const char *name;
	struct i2c_board_info board_info;
	u32 input;
	u32 output;
	unsigned can_route:1;
	struct vpif_interface vpif_if;
};

struct vpif_display_config {
	int (*set_clock)(int, int);
	struct vpif_subdev_info *subdevinfo;
	int subdev_count;
	const char **output;
	int output_count;
	const char *card_name;
};

struct vpif_input {
	struct v4l2_input input;
	const char *subdev_name;
};

#define VPIF_CAPTURE_MAX_CHANNELS	2

struct vpif_capture_chan_config {
	const struct vpif_input *inputs;
	int input_count;
};

struct vpif_capture_config {
	int (*setup_input_channel_mode)(int);
	int (*setup_input_path)(int, const char *);
	struct vpif_capture_chan_config chan_config[VPIF_CAPTURE_MAX_CHANNELS];
	struct vpif_subdev_info *subdev_info;
	int subdev_count;
	const char *card_name;
};

void dm646x_setup_vpif(struct vpif_display_config *,
		       struct vpif_capture_config *);

#endif /* __ASM_ARCH_DM646X_H */