Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 208134
b: refs/heads/master
c: 52fd3dd
h: refs/heads/master
v: v3
  • Loading branch information
Andy Walls authored and Mauro Carvalho Chehab committed Aug 9, 2010
1 parent a368bfb commit b962da1
Show file tree
Hide file tree
Showing 5 changed files with 1,420 additions and 2 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 260e689ba237fb513b49e98841d98e93ea639c75
refs/heads/master: 52fd3dda130d03ae5c2bbdcbe81f6e083c051e12
2 changes: 1 addition & 1 deletion trunk/drivers/media/video/cx25840/Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
cx25840-objs := cx25840-core.o cx25840-audio.o cx25840-firmware.o \
cx25840-vbi.o
cx25840-vbi.o cx25840-ir.o

obj-$(CONFIG_VIDEO_CX25840) += cx25840.o

Expand Down
128 changes: 128 additions & 0 deletions trunk/drivers/media/video/cx25840/cx25840-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@
*
* CX23885 support by Steven Toth <stoth@linuxtv.org>.
*
* CX2388[578] IRQ handling, IO Pin mux configuration and other small fixes are
* Copyright (C) 2010 Andy Walls <awalls@md.metrocast.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
Expand Down Expand Up @@ -48,6 +51,28 @@ MODULE_DESCRIPTION("Conexant CX25840 audio/video decoder driver");
MODULE_AUTHOR("Ulf Eklund, Chris Kennedy, Hans Verkuil, Tyler Trafford");
MODULE_LICENSE("GPL");

#define CX25840_VID_INT_STAT_REG 0x410
#define CX25840_VID_INT_STAT_BITS 0x0000ffff
#define CX25840_VID_INT_MASK_BITS 0xffff0000
#define CX25840_VID_INT_MASK_SHFT 16
#define CX25840_VID_INT_MASK_REG 0x412

#define CX23885_AUD_MC_INT_MASK_REG 0x80c
#define CX23885_AUD_MC_INT_STAT_BITS 0xffff0000
#define CX23885_AUD_MC_INT_CTRL_BITS 0x0000ffff
#define CX23885_AUD_MC_INT_STAT_SHFT 16

#define CX25840_AUD_INT_CTRL_REG 0x812
#define CX25840_AUD_INT_STAT_REG 0x813

#define CX23885_PIN_CTRL_IRQ_REG 0x123
#define CX23885_PIN_CTRL_IRQ_IR_STAT 0x40
#define CX23885_PIN_CTRL_IRQ_AUD_STAT 0x20
#define CX23885_PIN_CTRL_IRQ_VID_STAT 0x10

#define CX25840_IR_STATS_REG 0x210
#define CX25840_IR_IRQEN_REG 0x214

static int cx25840_debug;

module_param_named(debug,cx25840_debug, int, 0644);
Expand Down Expand Up @@ -137,6 +162,14 @@ int cx25840_and_or(struct i2c_client *client, u16 addr, unsigned and_mask,
or_value);
}

int cx25840_and_or4(struct i2c_client *client, u16 addr, u32 and_mask,
u32 or_value)
{
return cx25840_write4(client, addr,
(cx25840_read4(client, addr) & and_mask) |
or_value);
}

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

static int set_input(struct i2c_client *client, enum cx25840_video_input vid_input,
Expand Down Expand Up @@ -592,6 +625,13 @@ static void cx23885_initialize(struct i2c_client *client)

/* start microcontroller */
cx25840_and_or(client, 0x803, ~0x10, 0x10);

/* Disable and clear video interrupts - we don't use them */
cx25840_write4(client, CX25840_VID_INT_STAT_REG, 0xffffffff);

/* Disable and clear audio interrupts - we don't use them */
cx25840_write(client, CX25840_AUD_INT_CTRL_REG, 0xff);
cx25840_write(client, CX25840_AUD_INT_STAT_REG, 0xff);
}

/* ----------------------------------------------------------------------- */
Expand Down Expand Up @@ -1748,9 +1788,93 @@ static int cx25840_log_status(struct v4l2_subdev *sd)
log_video_status(client);
if (!is_cx2583x(state))
log_audio_status(client);
cx25840_ir_log_status(sd);
return 0;
}

static int cx23885_irq_handler(struct v4l2_subdev *sd, u32 status,
bool *handled)
{
struct cx25840_state *state = to_state(sd);
struct i2c_client *c = v4l2_get_subdevdata(sd);
u8 irq_stat, aud_stat, aud_en, ir_stat, ir_en;
u32 vid_stat, aud_mc_stat;
bool block_handled;
int ret = 0;

irq_stat = cx25840_read(c, CX23885_PIN_CTRL_IRQ_REG);
v4l_dbg(2, cx25840_debug, c, "AV Core IRQ status (entry): %s %s %s\n",
irq_stat & CX23885_PIN_CTRL_IRQ_IR_STAT ? "ir" : " ",
irq_stat & CX23885_PIN_CTRL_IRQ_AUD_STAT ? "aud" : " ",
irq_stat & CX23885_PIN_CTRL_IRQ_VID_STAT ? "vid" : " ");

if ((is_cx23885(state) || is_cx23887(state))) {
ir_stat = cx25840_read(c, CX25840_IR_STATS_REG);
ir_en = cx25840_read(c, CX25840_IR_IRQEN_REG);
v4l_dbg(2, cx25840_debug, c,
"AV Core ir IRQ status: %#04x disables: %#04x\n",
ir_stat, ir_en);
if (irq_stat & CX23885_PIN_CTRL_IRQ_IR_STAT) {
block_handled = false;
ret = cx25840_ir_irq_handler(sd,
status, &block_handled);
if (block_handled)
*handled = true;
}
}

aud_stat = cx25840_read(c, CX25840_AUD_INT_STAT_REG);
aud_en = cx25840_read(c, CX25840_AUD_INT_CTRL_REG);
v4l_dbg(2, cx25840_debug, c,
"AV Core audio IRQ status: %#04x disables: %#04x\n",
aud_stat, aud_en);
aud_mc_stat = cx25840_read4(c, CX23885_AUD_MC_INT_MASK_REG);
v4l_dbg(2, cx25840_debug, c,
"AV Core audio MC IRQ status: %#06x enables: %#06x\n",
aud_mc_stat >> CX23885_AUD_MC_INT_STAT_SHFT,
aud_mc_stat & CX23885_AUD_MC_INT_CTRL_BITS);
if (irq_stat & CX23885_PIN_CTRL_IRQ_AUD_STAT) {
if (aud_stat) {
cx25840_write(c, CX25840_AUD_INT_STAT_REG, aud_stat);
*handled = true;
}
}

vid_stat = cx25840_read4(c, CX25840_VID_INT_STAT_REG);
v4l_dbg(2, cx25840_debug, c,
"AV Core video IRQ status: %#06x disables: %#06x\n",
vid_stat & CX25840_VID_INT_STAT_BITS,
vid_stat >> CX25840_VID_INT_MASK_SHFT);
if (irq_stat & CX23885_PIN_CTRL_IRQ_VID_STAT) {
if (vid_stat & CX25840_VID_INT_STAT_BITS) {
cx25840_write4(c, CX25840_VID_INT_STAT_REG, vid_stat);
*handled = true;
}
}

irq_stat = cx25840_read(c, CX23885_PIN_CTRL_IRQ_REG);
v4l_dbg(2, cx25840_debug, c, "AV Core IRQ status (exit): %s %s %s\n",
irq_stat & CX23885_PIN_CTRL_IRQ_IR_STAT ? "ir" : " ",
irq_stat & CX23885_PIN_CTRL_IRQ_AUD_STAT ? "aud" : " ",
irq_stat & CX23885_PIN_CTRL_IRQ_VID_STAT ? "vid" : " ");

return ret;
}

static int cx25840_irq_handler(struct v4l2_subdev *sd, u32 status,
bool *handled)
{
struct cx25840_state *state = to_state(sd);

*handled = false;

/* Only support the CX2388[578] AV Core for now */
if (is_cx2388x(state))
return cx23885_irq_handler(sd, status, handled);

return -ENODEV;
}

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

static const struct v4l2_subdev_core_ops cx25840_core_ops = {
Expand All @@ -1767,6 +1891,7 @@ static const struct v4l2_subdev_core_ops cx25840_core_ops = {
.g_register = cx25840_g_register,
.s_register = cx25840_s_register,
#endif
.interrupt_service_routine = cx25840_irq_handler,
};

static const struct v4l2_subdev_tuner_ops cx25840_tuner_ops = {
Expand Down Expand Up @@ -1801,6 +1926,7 @@ static const struct v4l2_subdev_ops cx25840_ops = {
.audio = &cx25840_audio_ops,
.video = &cx25840_video_ops,
.vbi = &cx25840_vbi_ops,
.ir = &cx25840_ir_ops,
};

/* ----------------------------------------------------------------------- */
Expand Down Expand Up @@ -1942,13 +2068,15 @@ static int cx25840_probe(struct i2c_client *client,
state->id = id;
state->rev = device_id;

cx25840_ir_probe(sd);
return 0;
}

static int cx25840_remove(struct i2c_client *client)
{
struct v4l2_subdev *sd = i2c_get_clientdata(client);

cx25840_ir_remove(sd);
v4l2_device_unregister_subdev(sd);
kfree(to_state(sd));
return 0;
Expand Down
28 changes: 28 additions & 0 deletions trunk/drivers/media/video/cx25840/cx25840-core.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@
providing this information. */
#define CX25840_CID_ENABLE_PVR150_WORKAROUND (V4L2_CID_PRIVATE_BASE+0)

struct cx25840_ir_state;

struct cx25840_state {
struct i2c_client *c;
struct v4l2_subdev sd;
Expand All @@ -52,6 +54,7 @@ struct cx25840_state {
int is_initialized;
wait_queue_head_t fw_wait; /* wake up when the fw load is finished */
struct work_struct fw_work; /* work entry for fw load */
struct cx25840_ir_state *ir_state;
};

static inline struct cx25840_state *to_state(struct v4l2_subdev *sd)
Expand All @@ -77,13 +80,30 @@ static inline bool is_cx2388x(struct cx25840_state *state)
state->id == V4L2_IDENT_CX23888_AV;
}

static inline bool is_cx23885(struct cx25840_state *state)
{
return state->id == V4L2_IDENT_CX23885_AV;
}

static inline bool is_cx23887(struct cx25840_state *state)
{
return state->id == V4L2_IDENT_CX23887_AV;
}

static inline bool is_cx23888(struct cx25840_state *state)
{
return state->id == V4L2_IDENT_CX23888_AV;
}

/* ----------------------------------------------------------------------- */
/* cx25850-core.c */
int cx25840_write(struct i2c_client *client, u16 addr, u8 value);
int cx25840_write4(struct i2c_client *client, u16 addr, u32 value);
u8 cx25840_read(struct i2c_client *client, u16 addr);
u32 cx25840_read4(struct i2c_client *client, u16 addr);
int cx25840_and_or(struct i2c_client *client, u16 addr, unsigned mask, u8 value);
int cx25840_and_or4(struct i2c_client *client, u16 addr, u32 and_mask,
u32 or_value);
void cx25840_std_setup(struct i2c_client *client);

/* ----------------------------------------------------------------------- */
Expand All @@ -104,4 +124,12 @@ int cx25840_s_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *
int cx25840_g_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *fmt);
int cx25840_decode_vbi_line(struct v4l2_subdev *sd, struct v4l2_decode_vbi_line *vbi);

/* ----------------------------------------------------------------------- */
/* cx25850-ir.c */
extern const struct v4l2_subdev_ir_ops cx25840_ir_ops;
int cx25840_ir_log_status(struct v4l2_subdev *sd);
int cx25840_ir_irq_handler(struct v4l2_subdev *sd, u32 status, bool *handled);
int cx25840_ir_probe(struct v4l2_subdev *sd);
int cx25840_ir_remove(struct v4l2_subdev *sd);

#endif
Loading

0 comments on commit b962da1

Please sign in to comment.