Commit 8e4c97e0 authored by Philipp Zabel's avatar Philipp Zabel Committed by Mauro Carvalho Chehab

media: tvp5150: Add sync lock interrupt handling

This patch adds an optional interrupt handler to handle the sync
lock interrupt and sync lock status.
Signed-off-by: default avatarPhilipp Zabel <p.zabel@pengutronix.de>
Signed-off-by: default avatarLucas Stach <l.stach@pengutronix.de>
[m.felsch@pengutronix.de: move added .g_std callback to separate patch]
Signed-off-by: default avatarMarco Felsch <m.felsch@pengutronix.de>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab+samsung@kernel.org>
parent 8105e1bc
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include <linux/videodev2.h> #include <linux/videodev2.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/gpio/consumer.h> #include <linux/gpio/consumer.h>
#include <linux/interrupt.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/of_graph.h> #include <linux/of_graph.h>
#include <linux/regmap.h> #include <linux/regmap.h>
...@@ -58,12 +59,14 @@ struct tvp5150 { ...@@ -58,12 +59,14 @@ struct tvp5150 {
struct v4l2_ctrl_handler hdl; struct v4l2_ctrl_handler hdl;
struct v4l2_rect rect; struct v4l2_rect rect;
struct regmap *regmap; struct regmap *regmap;
int irq;
v4l2_std_id norm; /* Current set standard */ v4l2_std_id norm; /* Current set standard */
v4l2_std_id detected_norm; v4l2_std_id detected_norm;
u32 input; u32 input;
u32 output; u32 output;
int enable; int enable;
bool lock;
u16 dev_id; u16 dev_id;
u16 rom_ver; u16 rom_ver;
...@@ -797,6 +800,33 @@ static v4l2_std_id tvp5150_read_std(struct v4l2_subdev *sd) ...@@ -797,6 +800,33 @@ static v4l2_std_id tvp5150_read_std(struct v4l2_subdev *sd)
} }
} }
static irqreturn_t tvp5150_isr(int irq, void *dev_id)
{
struct tvp5150 *decoder = dev_id;
struct regmap *map = decoder->regmap;
unsigned int active = 0, status = 0;
regmap_read(map, TVP5150_INT_STATUS_REG_A, &status);
if (status) {
regmap_write(map, TVP5150_INT_STATUS_REG_A, status);
if (status & TVP5150_INT_A_LOCK)
decoder->lock = !!(status & TVP5150_INT_A_LOCK_STATUS);
return IRQ_HANDLED;
}
regmap_read(map, TVP5150_INT_ACTIVE_REG_B, &active);
if (active) {
status = 0;
regmap_read(map, TVP5150_INT_STATUS_REG_B, &status);
if (status)
regmap_write(map, TVP5150_INT_RESET_REG_B, status);
}
return IRQ_HANDLED;
}
static int tvp5150_reset(struct v4l2_subdev *sd, u32 val) static int tvp5150_reset(struct v4l2_subdev *sd, u32 val)
{ {
struct tvp5150 *decoder = to_tvp5150(sd); struct tvp5150 *decoder = to_tvp5150(sd);
...@@ -805,8 +835,19 @@ static int tvp5150_reset(struct v4l2_subdev *sd, u32 val) ...@@ -805,8 +835,19 @@ static int tvp5150_reset(struct v4l2_subdev *sd, u32 val)
/* Initializes TVP5150 to its default values */ /* Initializes TVP5150 to its default values */
tvp5150_write_inittab(sd, tvp5150_init_default); tvp5150_write_inittab(sd, tvp5150_init_default);
/* Configure pins: FID, VSYNC, GPCL/VBLK, SCLK */ if (decoder->irq) {
regmap_write(map, TVP5150_CONF_SHARED_PIN, 0x2); /* Configure pins: FID, VSYNC, INTREQ, SCLK */
regmap_write(map, TVP5150_CONF_SHARED_PIN, 0x0);
/* Set interrupt polarity to active high */
regmap_write(map, TVP5150_INT_CONF, TVP5150_VDPOE | 0x1);
regmap_write(map, TVP5150_INTT_CONFIG_REG_B, 0x1);
} else {
/* Configure pins: FID, VSYNC, GPCL/VBLK, SCLK */
regmap_write(map, TVP5150_CONF_SHARED_PIN, 0x2);
/* Keep interrupt polarity active low */
regmap_write(map, TVP5150_INT_CONF, TVP5150_VDPOE);
regmap_write(map, TVP5150_INTT_CONFIG_REG_B, 0x0);
}
/* Initializes VDP registers */ /* Initializes VDP registers */
tvp5150_vdp_init(sd); tvp5150_vdp_init(sd);
...@@ -1108,7 +1149,7 @@ static const struct media_entity_operations tvp5150_sd_media_ops = { ...@@ -1108,7 +1149,7 @@ static const struct media_entity_operations tvp5150_sd_media_ops = {
static int tvp5150_s_stream(struct v4l2_subdev *sd, int enable) static int tvp5150_s_stream(struct v4l2_subdev *sd, int enable)
{ {
struct tvp5150 *decoder = to_tvp5150(sd); struct tvp5150 *decoder = to_tvp5150(sd);
unsigned int mask, val = 0; unsigned int mask, val = 0, int_val = 0;
mask = TVP5150_MISC_CTL_YCBCR_OE | TVP5150_MISC_CTL_SYNC_OE | mask = TVP5150_MISC_CTL_YCBCR_OE | TVP5150_MISC_CTL_SYNC_OE |
TVP5150_MISC_CTL_CLOCK_OE; TVP5150_MISC_CTL_CLOCK_OE;
...@@ -1123,9 +1164,15 @@ static int tvp5150_s_stream(struct v4l2_subdev *sd, int enable) ...@@ -1123,9 +1164,15 @@ static int tvp5150_s_stream(struct v4l2_subdev *sd, int enable)
val = TVP5150_MISC_CTL_YCBCR_OE | TVP5150_MISC_CTL_CLOCK_OE; val = TVP5150_MISC_CTL_YCBCR_OE | TVP5150_MISC_CTL_CLOCK_OE;
if (decoder->mbus_type == V4L2_MBUS_PARALLEL) if (decoder->mbus_type == V4L2_MBUS_PARALLEL)
val |= TVP5150_MISC_CTL_SYNC_OE; val |= TVP5150_MISC_CTL_SYNC_OE;
int_val = TVP5150_INT_A_LOCK;
} }
regmap_update_bits(decoder->regmap, TVP5150_MISC_CTL, mask, val); regmap_update_bits(decoder->regmap, TVP5150_MISC_CTL, mask, val);
if (decoder->irq)
/* Enable / Disable lock interrupt */
regmap_update_bits(decoder->regmap, TVP5150_INT_ENABLE_REG_A,
TVP5150_INT_A_LOCK, int_val);
return 0; return 0;
} }
...@@ -1676,7 +1723,17 @@ static int tvp5150_probe(struct i2c_client *c, ...@@ -1676,7 +1723,17 @@ static int tvp5150_probe(struct i2c_client *c,
tvp5150_set_default(tvp5150_read_std(sd), &core->rect); tvp5150_set_default(tvp5150_read_std(sd), &core->rect);
core->irq = c->irq;
tvp5150_reset(sd, 0); /* Calls v4l2_ctrl_handler_setup() */ tvp5150_reset(sd, 0); /* Calls v4l2_ctrl_handler_setup() */
if (c->irq) {
res = devm_request_threaded_irq(&c->dev, c->irq, NULL,
tvp5150_isr, IRQF_TRIGGER_HIGH |
IRQF_ONESHOT, "tvp5150", core);
if (res)
return res;
} else {
core->lock = true;
}
res = v4l2_async_register_subdev(sd); res = v4l2_async_register_subdev(sd);
if (res < 0) if (res < 0)
......
...@@ -125,8 +125,11 @@ ...@@ -125,8 +125,11 @@
#define TVP5150_TELETEXT_FIL_ENA 0xbb /* Teletext filter enable */ #define TVP5150_TELETEXT_FIL_ENA 0xbb /* Teletext filter enable */
/* Reserved BCh-BFh */ /* Reserved BCh-BFh */
#define TVP5150_INT_STATUS_REG_A 0xc0 /* Interrupt status register A */ #define TVP5150_INT_STATUS_REG_A 0xc0 /* Interrupt status register A */
#define TVP5150_INT_A_LOCK_STATUS BIT(7)
#define TVP5150_INT_A_LOCK BIT(6)
#define TVP5150_INT_ENABLE_REG_A 0xc1 /* Interrupt enable register A */ #define TVP5150_INT_ENABLE_REG_A 0xc1 /* Interrupt enable register A */
#define TVP5150_INT_CONF 0xc2 /* Interrupt configuration */ #define TVP5150_INT_CONF 0xc2 /* Interrupt configuration */
#define TVP5150_VDPOE BIT(2)
#define TVP5150_VDP_CONF_RAM_DATA 0xc3 /* VDP configuration RAM data */ #define TVP5150_VDP_CONF_RAM_DATA 0xc3 /* VDP configuration RAM data */
#define TVP5150_CONF_RAM_ADDR_LOW 0xc4 /* Configuration RAM address low byte */ #define TVP5150_CONF_RAM_ADDR_LOW 0xc4 /* Configuration RAM address low byte */
#define TVP5150_CONF_RAM_ADDR_HIGH 0xc5 /* Configuration RAM address high byte */ #define TVP5150_CONF_RAM_ADDR_HIGH 0xc5 /* Configuration RAM address high byte */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment