Commit 67ec09fd authored by Hans Verkuil's avatar Hans Verkuil Committed by Mauro Carvalho Chehab

V4L/DVB (9835): ivtv/ivtvfb: convert to v4l2_device/v4l2_subdev.

Signed-off-by: default avatarHans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent ca085fb9
...@@ -63,7 +63,7 @@ int ivtv_queryctrl(struct file *file, void *fh, struct v4l2_queryctrl *qctrl) ...@@ -63,7 +63,7 @@ int ivtv_queryctrl(struct file *file, void *fh, struct v4l2_queryctrl *qctrl)
case V4L2_CID_HUE: case V4L2_CID_HUE:
case V4L2_CID_SATURATION: case V4L2_CID_SATURATION:
case V4L2_CID_CONTRAST: case V4L2_CID_CONTRAST:
if (itv->video_dec_func(itv, VIDIOC_QUERYCTRL, qctrl)) if (v4l2_subdev_call(itv->sd_video, core, queryctrl, qctrl))
qctrl->flags |= V4L2_CTRL_FLAG_DISABLED; qctrl->flags |= V4L2_CTRL_FLAG_DISABLED;
return 0; return 0;
...@@ -73,7 +73,7 @@ int ivtv_queryctrl(struct file *file, void *fh, struct v4l2_queryctrl *qctrl) ...@@ -73,7 +73,7 @@ int ivtv_queryctrl(struct file *file, void *fh, struct v4l2_queryctrl *qctrl)
case V4L2_CID_AUDIO_BASS: case V4L2_CID_AUDIO_BASS:
case V4L2_CID_AUDIO_TREBLE: case V4L2_CID_AUDIO_TREBLE:
case V4L2_CID_AUDIO_LOUDNESS: case V4L2_CID_AUDIO_LOUDNESS:
if (ivtv_i2c_hw(itv, itv->card->hw_audio_ctrl, VIDIOC_QUERYCTRL, qctrl)) if (v4l2_subdev_call(itv->sd_audio, core, queryctrl, qctrl))
qctrl->flags |= V4L2_CTRL_FLAG_DISABLED; qctrl->flags |= V4L2_CTRL_FLAG_DISABLED;
return 0; return 0;
...@@ -122,7 +122,7 @@ static int ivtv_s_ctrl(struct ivtv *itv, struct v4l2_control *vctrl) ...@@ -122,7 +122,7 @@ static int ivtv_s_ctrl(struct ivtv *itv, struct v4l2_control *vctrl)
case V4L2_CID_HUE: case V4L2_CID_HUE:
case V4L2_CID_SATURATION: case V4L2_CID_SATURATION:
case V4L2_CID_CONTRAST: case V4L2_CID_CONTRAST:
return itv->video_dec_func(itv, VIDIOC_S_CTRL, vctrl); return v4l2_subdev_call(itv->sd_video, core, s_ctrl, vctrl);
case V4L2_CID_AUDIO_VOLUME: case V4L2_CID_AUDIO_VOLUME:
case V4L2_CID_AUDIO_MUTE: case V4L2_CID_AUDIO_MUTE:
...@@ -130,7 +130,7 @@ static int ivtv_s_ctrl(struct ivtv *itv, struct v4l2_control *vctrl) ...@@ -130,7 +130,7 @@ static int ivtv_s_ctrl(struct ivtv *itv, struct v4l2_control *vctrl)
case V4L2_CID_AUDIO_BASS: case V4L2_CID_AUDIO_BASS:
case V4L2_CID_AUDIO_TREBLE: case V4L2_CID_AUDIO_TREBLE:
case V4L2_CID_AUDIO_LOUDNESS: case V4L2_CID_AUDIO_LOUDNESS:
return ivtv_i2c_hw(itv, itv->card->hw_audio_ctrl, VIDIOC_S_CTRL, vctrl); return v4l2_subdev_call(itv->sd_audio, core, s_ctrl, vctrl);
default: default:
IVTV_DEBUG_IOCTL("invalid control 0x%x\n", vctrl->id); IVTV_DEBUG_IOCTL("invalid control 0x%x\n", vctrl->id);
...@@ -147,7 +147,7 @@ static int ivtv_g_ctrl(struct ivtv *itv, struct v4l2_control *vctrl) ...@@ -147,7 +147,7 @@ static int ivtv_g_ctrl(struct ivtv *itv, struct v4l2_control *vctrl)
case V4L2_CID_HUE: case V4L2_CID_HUE:
case V4L2_CID_SATURATION: case V4L2_CID_SATURATION:
case V4L2_CID_CONTRAST: case V4L2_CID_CONTRAST:
return itv->video_dec_func(itv, VIDIOC_G_CTRL, vctrl); return v4l2_subdev_call(itv->sd_video, core, g_ctrl, vctrl);
case V4L2_CID_AUDIO_VOLUME: case V4L2_CID_AUDIO_VOLUME:
case V4L2_CID_AUDIO_MUTE: case V4L2_CID_AUDIO_MUTE:
...@@ -155,7 +155,7 @@ static int ivtv_g_ctrl(struct ivtv *itv, struct v4l2_control *vctrl) ...@@ -155,7 +155,7 @@ static int ivtv_g_ctrl(struct ivtv *itv, struct v4l2_control *vctrl)
case V4L2_CID_AUDIO_BASS: case V4L2_CID_AUDIO_BASS:
case V4L2_CID_AUDIO_TREBLE: case V4L2_CID_AUDIO_TREBLE:
case V4L2_CID_AUDIO_LOUDNESS: case V4L2_CID_AUDIO_LOUDNESS:
return ivtv_i2c_hw(itv, itv->card->hw_audio_ctrl, VIDIOC_G_CTRL, vctrl); return v4l2_subdev_call(itv->sd_audio, core, g_ctrl, vctrl);
default: default:
IVTV_DEBUG_IOCTL("invalid control 0x%x\n", vctrl->id); IVTV_DEBUG_IOCTL("invalid control 0x%x\n", vctrl->id);
return -EINVAL; return -EINVAL;
...@@ -268,7 +268,7 @@ int ivtv_s_ext_ctrls(struct file *file, void *fh, struct v4l2_ext_controls *c) ...@@ -268,7 +268,7 @@ int ivtv_s_ext_ctrls(struct file *file, void *fh, struct v4l2_ext_controls *c)
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
fmt.fmt.pix.width = itv->params.width / (is_mpeg1 ? 2 : 1); fmt.fmt.pix.width = itv->params.width / (is_mpeg1 ? 2 : 1);
fmt.fmt.pix.height = itv->params.height; fmt.fmt.pix.height = itv->params.height;
itv->video_dec_func(itv, VIDIOC_S_FMT, &fmt); v4l2_subdev_call(itv->sd_video, video, s_fmt, &fmt);
} }
err = cx2341x_update(itv, ivtv_api_func, &itv->params, &p); err = cx2341x_update(itv, ivtv_api_func, &itv->params, &p);
if (!err && itv->params.stream_vbi_fmt != p.stream_vbi_fmt) if (!err && itv->params.stream_vbi_fmt != p.stream_vbi_fmt)
...@@ -279,7 +279,7 @@ int ivtv_s_ext_ctrls(struct file *file, void *fh, struct v4l2_ext_controls *c) ...@@ -279,7 +279,7 @@ int ivtv_s_ext_ctrls(struct file *file, void *fh, struct v4l2_ext_controls *c)
/* The audio clock of the digitizer must match the codec sample /* The audio clock of the digitizer must match the codec sample
rate otherwise you get some very strange effects. */ rate otherwise you get some very strange effects. */
if (idx < sizeof(freqs)) if (idx < sizeof(freqs))
ivtv_call_i2c_clients(itv, VIDIOC_INT_AUDIO_CLOCK_FREQ, &freqs[idx]); ivtv_call_all(itv, audio, s_clock_freq, freqs[idx]);
return err; return err;
} }
return -EINVAL; return -EINVAL;
......
This diff is collapsed.
...@@ -61,6 +61,7 @@ ...@@ -61,6 +61,7 @@
#include <linux/dvb/audio.h> #include <linux/dvb/audio.h>
#include <media/v4l2-common.h> #include <media/v4l2-common.h>
#include <media/v4l2-ioctl.h> #include <media/v4l2-ioctl.h>
#include <media/v4l2-device.h>
#include <media/tuner.h> #include <media/tuner.h>
#include <media/cx2341x.h> #include <media/cx2341x.h>
...@@ -113,9 +114,6 @@ ...@@ -113,9 +114,6 @@
#define IVTV_REG_VPU (0x9058) #define IVTV_REG_VPU (0x9058)
#define IVTV_REG_APU (0xA064) #define IVTV_REG_APU (0xA064)
/* i2c stuff */
#define I2C_CLIENTS_MAX 16
/* debugging */ /* debugging */
extern int ivtv_debug; extern int ivtv_debug;
...@@ -132,12 +130,10 @@ extern int ivtv_debug; ...@@ -132,12 +130,10 @@ extern int ivtv_debug;
/* Flag to turn on high volume debugging */ /* Flag to turn on high volume debugging */
#define IVTV_DBGFLG_HIGHVOL (1 << 10) #define IVTV_DBGFLG_HIGHVOL (1 << 10)
/* NOTE: extra space before comma in 'itv->num , ## args' is required for
gcc-2.95, otherwise it won't compile. */
#define IVTV_DEBUG(x, type, fmt, args...) \ #define IVTV_DEBUG(x, type, fmt, args...) \
do { \ do { \
if ((x) & ivtv_debug) \ if ((x) & ivtv_debug) \
printk(KERN_INFO "ivtv%d " type ": " fmt, itv->num , ## args); \ v4l2_info(&itv->device, " " type ": " fmt , ##args); \
} while (0) } while (0)
#define IVTV_DEBUG_WARN(fmt, args...) IVTV_DEBUG(IVTV_DBGFLG_WARN, "warn", fmt , ## args) #define IVTV_DEBUG_WARN(fmt, args...) IVTV_DEBUG(IVTV_DBGFLG_WARN, "warn", fmt , ## args)
#define IVTV_DEBUG_INFO(fmt, args...) IVTV_DEBUG(IVTV_DBGFLG_INFO, "info", fmt , ## args) #define IVTV_DEBUG_INFO(fmt, args...) IVTV_DEBUG(IVTV_DBGFLG_INFO, "info", fmt , ## args)
...@@ -153,7 +149,7 @@ extern int ivtv_debug; ...@@ -153,7 +149,7 @@ extern int ivtv_debug;
#define IVTV_DEBUG_HIGH_VOL(x, type, fmt, args...) \ #define IVTV_DEBUG_HIGH_VOL(x, type, fmt, args...) \
do { \ do { \
if (((x) & ivtv_debug) && (ivtv_debug & IVTV_DBGFLG_HIGHVOL)) \ if (((x) & ivtv_debug) && (ivtv_debug & IVTV_DBGFLG_HIGHVOL)) \
printk(KERN_INFO "ivtv%d " type ": " fmt, itv->num , ## args); \ v4l2_info(&itv->device, " " type ": " fmt , ##args); \
} while (0) } while (0)
#define IVTV_DEBUG_HI_WARN(fmt, args...) IVTV_DEBUG_HIGH_VOL(IVTV_DBGFLG_WARN, "warn", fmt , ## args) #define IVTV_DEBUG_HI_WARN(fmt, args...) IVTV_DEBUG_HIGH_VOL(IVTV_DBGFLG_WARN, "warn", fmt , ## args)
#define IVTV_DEBUG_HI_INFO(fmt, args...) IVTV_DEBUG_HIGH_VOL(IVTV_DBGFLG_INFO, "info", fmt , ## args) #define IVTV_DEBUG_HI_INFO(fmt, args...) IVTV_DEBUG_HIGH_VOL(IVTV_DBGFLG_INFO, "info", fmt , ## args)
...@@ -167,9 +163,9 @@ extern int ivtv_debug; ...@@ -167,9 +163,9 @@ extern int ivtv_debug;
#define IVTV_DEBUG_HI_YUV(fmt, args...) IVTV_DEBUG_HIGH_VOL(IVTV_DBGFLG_YUV, "yuv", fmt , ## args) #define IVTV_DEBUG_HI_YUV(fmt, args...) IVTV_DEBUG_HIGH_VOL(IVTV_DBGFLG_YUV, "yuv", fmt , ## args)
/* Standard kernel messages */ /* Standard kernel messages */
#define IVTV_ERR(fmt, args...) printk(KERN_ERR "ivtv%d: " fmt, itv->num , ## args) #define IVTV_ERR(fmt, args...) v4l2_err(&itv->device, fmt , ## args)
#define IVTV_WARN(fmt, args...) printk(KERN_WARNING "ivtv%d: " fmt, itv->num , ## args) #define IVTV_WARN(fmt, args...) v4l2_warn(&itv->device, fmt , ## args)
#define IVTV_INFO(fmt, args...) printk(KERN_INFO "ivtv%d: " fmt, itv->num , ## args) #define IVTV_INFO(fmt, args...) v4l2_info(&itv->device, fmt , ## args)
/* output modes (cx23415 only) */ /* output modes (cx23415 only) */
#define OUT_NONE 0 #define OUT_NONE 0
...@@ -596,8 +592,6 @@ struct ivtv_card; ...@@ -596,8 +592,6 @@ struct ivtv_card;
/* Struct to hold info about ivtv cards */ /* Struct to hold info about ivtv cards */
struct ivtv { struct ivtv {
/* General fixed card data */ /* General fixed card data */
int num; /* board number, -1 during init! */
char name[8]; /* board name for printk and interrupts (e.g. 'ivtv0') */
struct pci_dev *dev; /* PCI device */ struct pci_dev *dev; /* PCI device */
const struct ivtv_card *card; /* card information */ const struct ivtv_card *card; /* card information */
const char *card_name; /* full name of the card */ const char *card_name; /* full name of the card */
...@@ -609,14 +603,18 @@ struct ivtv { ...@@ -609,14 +603,18 @@ struct ivtv {
u32 v4l2_cap; /* V4L2 capabilities of card */ u32 v4l2_cap; /* V4L2 capabilities of card */
u32 hw_flags; /* hardware description of the board */ u32 hw_flags; /* hardware description of the board */
v4l2_std_id tuner_std; /* the norm of the card's tuner (fixed) */ v4l2_std_id tuner_std; /* the norm of the card's tuner (fixed) */
/* controlling video decoder function */ struct v4l2_subdev *sd_video; /* controlling video decoder subdev */
int (*video_dec_func)(struct ivtv *, unsigned int, void *); struct v4l2_subdev *sd_audio; /* controlling audio subdev */
struct v4l2_subdev *sd_muxer; /* controlling audio muxer subdev */
u32 base_addr; /* PCI resource base address */ u32 base_addr; /* PCI resource base address */
volatile void __iomem *enc_mem; /* pointer to mapped encoder memory */ volatile void __iomem *enc_mem; /* pointer to mapped encoder memory */
volatile void __iomem *dec_mem; /* pointer to mapped decoder memory */ volatile void __iomem *dec_mem; /* pointer to mapped decoder memory */
volatile void __iomem *reg_mem; /* pointer to mapped registers */ volatile void __iomem *reg_mem; /* pointer to mapped registers */
struct ivtv_options options; /* user options */ struct ivtv_options options; /* user options */
struct v4l2_device device;
struct v4l2_subdev sd_gpio; /* GPIO sub-device */
u16 instance;
/* High-level state info */ /* High-level state info */
unsigned long i_flags; /* global ivtv flags */ unsigned long i_flags; /* global ivtv flags */
...@@ -676,7 +674,6 @@ struct ivtv { ...@@ -676,7 +674,6 @@ struct ivtv {
struct i2c_adapter i2c_adap; struct i2c_adapter i2c_adap;
struct i2c_algo_bit_data i2c_algo; struct i2c_algo_bit_data i2c_algo;
struct i2c_client i2c_client; struct i2c_client i2c_client;
struct i2c_client *i2c_clients[I2C_CLIENTS_MAX];/* pointers to all I2C clients */
int i2c_state; /* i2c bit state */ int i2c_state; /* i2c bit state */
struct mutex i2c_bus_lock; /* lock i2c bus */ struct mutex i2c_bus_lock; /* lock i2c bus */
...@@ -722,11 +719,13 @@ struct ivtv { ...@@ -722,11 +719,13 @@ struct ivtv {
struct osd_info *osd_info; /* ivtvfb private OSD info */ struct osd_info *osd_info; /* ivtvfb private OSD info */
}; };
static inline struct ivtv *to_ivtv(struct v4l2_device *dev)
{
return container_of(dev, struct ivtv, device);
}
/* Globals */ /* Globals */
extern struct ivtv *ivtv_cards[];
extern int ivtv_cards_active;
extern int ivtv_first_minor; extern int ivtv_first_minor;
extern spinlock_t ivtv_cards_lock;
/*==============Prototypes==================*/ /*==============Prototypes==================*/
...@@ -786,4 +785,19 @@ static inline int ivtv_raw_vbi(const struct ivtv *itv) ...@@ -786,4 +785,19 @@ static inline int ivtv_raw_vbi(const struct ivtv *itv)
#define write_dec_sync(val, addr) \ #define write_dec_sync(val, addr) \
do { write_dec(val, addr); read_dec(addr); } while (0) do { write_dec(val, addr); read_dec(addr); } while (0)
/* Call the specified callback for all subdevs matching hw (if 0, then
match them all). Ignore any errors. */
#define ivtv_call_hw(itv, hw, o, f, args...) \
__v4l2_device_call_subdevs(&(itv)->device, !(hw) || (sd->grp_id & (hw)), o, f , ##args)
#define ivtv_call_all(itv, o, f, args...) ivtv_call_hw(itv, 0, o, f , ##args)
/* Call the specified callback for all subdevs matching hw (if 0, then
match them all). If the callback returns an error other than 0 or
-ENOIOCTLCMD, then return with that error code. */
#define ivtv_call_hw_err(itv, hw, o, f, args...) \
__v4l2_device_call_subdevs_until_err(&(itv)->device, !(hw) || (sd->grp_id & (hw)), o, f , ##args)
#define ivtv_call_all_err(itv, o, f, args...) ivtv_call_hw_err(itv, 0, o, f , ##args)
#endif #endif
...@@ -155,7 +155,7 @@ static void ivtv_dualwatch(struct ivtv *itv) ...@@ -155,7 +155,7 @@ static void ivtv_dualwatch(struct ivtv *itv)
new_stereo_mode = itv->params.audio_properties & stereo_mask; new_stereo_mode = itv->params.audio_properties & stereo_mask;
memset(&vt, 0, sizeof(vt)); memset(&vt, 0, sizeof(vt));
ivtv_call_i2c_clients(itv, VIDIOC_G_TUNER, &vt); ivtv_call_all(itv, tuner, g_tuner, &vt);
if (vt.audmode == V4L2_TUNER_MODE_LANG1_LANG2 && (vt.rxsubchans & V4L2_TUNER_SUB_LANG2)) if (vt.audmode == V4L2_TUNER_MODE_LANG1_LANG2 && (vt.rxsubchans & V4L2_TUNER_SUB_LANG2))
new_stereo_mode = dual; new_stereo_mode = dual;
...@@ -857,7 +857,7 @@ int ivtv_v4l2_close(struct inode *inode, struct file *filp) ...@@ -857,7 +857,7 @@ int ivtv_v4l2_close(struct inode *inode, struct file *filp)
/* Mark that the radio is no longer in use */ /* Mark that the radio is no longer in use */
clear_bit(IVTV_F_I_RADIO_USER, &itv->i_flags); clear_bit(IVTV_F_I_RADIO_USER, &itv->i_flags);
/* Switch tuner to TV */ /* Switch tuner to TV */
ivtv_call_i2c_clients(itv, VIDIOC_S_STD, &itv->std); ivtv_call_all(itv, tuner, s_std, itv->std);
/* Select correct audio input (i.e. TV tuner or Line in) */ /* Select correct audio input (i.e. TV tuner or Line in) */
ivtv_audio_set_io(itv); ivtv_audio_set_io(itv);
if (itv->hw_flags & IVTV_HW_SAA711X) if (itv->hw_flags & IVTV_HW_SAA711X)
...@@ -865,7 +865,7 @@ int ivtv_v4l2_close(struct inode *inode, struct file *filp) ...@@ -865,7 +865,7 @@ int ivtv_v4l2_close(struct inode *inode, struct file *filp)
struct v4l2_crystal_freq crystal_freq; struct v4l2_crystal_freq crystal_freq;
crystal_freq.freq = SAA7115_FREQ_32_11_MHZ; crystal_freq.freq = SAA7115_FREQ_32_11_MHZ;
crystal_freq.flags = 0; crystal_freq.flags = 0;
ivtv_saa7115(itv, VIDIOC_INT_S_CRYSTAL_FREQ, &crystal_freq); ivtv_call_hw(itv, IVTV_HW_SAA711X, video, s_crystal_freq, &crystal_freq);
} }
if (atomic_read(&itv->capturing) > 0) { if (atomic_read(&itv->capturing) > 0) {
/* Undo video mute */ /* Undo video mute */
...@@ -952,15 +952,14 @@ static int ivtv_serialized_open(struct ivtv_stream *s, struct file *filp) ...@@ -952,15 +952,14 @@ static int ivtv_serialized_open(struct ivtv_stream *s, struct file *filp)
/* We have the radio */ /* We have the radio */
ivtv_mute(itv); ivtv_mute(itv);
/* Switch tuner to radio */ /* Switch tuner to radio */
ivtv_call_i2c_clients(itv, AUDC_SET_RADIO, NULL); ivtv_call_all(itv, tuner, s_radio);
/* Select the correct audio input (i.e. radio tuner) */ /* Select the correct audio input (i.e. radio tuner) */
ivtv_audio_set_io(itv); ivtv_audio_set_io(itv);
if (itv->hw_flags & IVTV_HW_SAA711X) if (itv->hw_flags & IVTV_HW_SAA711X) {
{
struct v4l2_crystal_freq crystal_freq; struct v4l2_crystal_freq crystal_freq;
crystal_freq.freq = SAA7115_FREQ_32_11_MHZ; crystal_freq.freq = SAA7115_FREQ_32_11_MHZ;
crystal_freq.flags = SAA7115_FREQ_FL_APLL; crystal_freq.flags = SAA7115_FREQ_FL_APLL;
ivtv_saa7115(itv, VIDIOC_INT_S_CRYSTAL_FREQ, &crystal_freq); ivtv_call_hw(itv, IVTV_HW_SAA711X, video, s_crystal_freq, &crystal_freq);
} }
/* Done! Unmute and continue. */ /* Done! Unmute and continue. */
ivtv_unmute(itv); ivtv_unmute(itv);
...@@ -981,37 +980,18 @@ static int ivtv_serialized_open(struct ivtv_stream *s, struct file *filp) ...@@ -981,37 +980,18 @@ static int ivtv_serialized_open(struct ivtv_stream *s, struct file *filp)
int ivtv_v4l2_open(struct inode *inode, struct file *filp) int ivtv_v4l2_open(struct inode *inode, struct file *filp)
{ {
int res, x, y = 0; int res;
struct ivtv *itv = NULL; struct ivtv *itv = NULL;
struct ivtv_stream *s = NULL; struct ivtv_stream *s = NULL;
int minor = iminor(inode); struct video_device *vdev = video_devdata(filp);
/* Find which card this open was on */
spin_lock(&ivtv_cards_lock);
for (x = 0; itv == NULL && x < ivtv_cards_active; x++) {
if (ivtv_cards[x] == NULL)
continue;
/* find out which stream this open was on */
for (y = 0; y < IVTV_MAX_STREAMS; y++) {
s = &ivtv_cards[x]->streams[y];
if (s->v4l2dev && s->v4l2dev->minor == minor) {
itv = ivtv_cards[x];
break;
}
}
}
spin_unlock(&ivtv_cards_lock);
if (itv == NULL) { s = video_get_drvdata(vdev);
/* Couldn't find a device registered itv = s->itv;
on that minor, shouldn't happen! */
printk(KERN_WARNING "No ivtv device found on minor %d\n", minor);
return -ENXIO;
}
mutex_lock(&itv->serialize_lock); mutex_lock(&itv->serialize_lock);
if (ivtv_init_on_first_open(itv)) { if (ivtv_init_on_first_open(itv)) {
IVTV_ERR("Failed to initialize on minor %d\n", minor); IVTV_ERR("Failed to initialize on minor %d\n",
s->v4l2dev->minor);
mutex_unlock(&itv->serialize_lock); mutex_unlock(&itv->serialize_lock);
return -ENXIO; return -ENXIO;
} }
......
...@@ -144,22 +144,9 @@ int ivtv_reset_tuner_gpio(void *dev, int component, int cmd, int value) ...@@ -144,22 +144,9 @@ int ivtv_reset_tuner_gpio(void *dev, int component, int cmd, int value)
return 0; return 0;
} }
void ivtv_gpio_init(struct ivtv *itv) static inline struct ivtv *sd_to_ivtv(struct v4l2_subdev *sd)
{ {
u16 pin = 0; return container_of(sd, struct ivtv, sd_gpio);
if (itv->card->xceive_pin)
pin = 1 << itv->card->xceive_pin;
if ((itv->card->gpio_init.direction | pin) == 0)
return;
IVTV_DEBUG_INFO("GPIO initial dir: %08x out: %08x\n",
read_reg(IVTV_REG_GPIO_DIR), read_reg(IVTV_REG_GPIO_OUT));
/* init output data then direction */
write_reg(itv->card->gpio_init.initial_value | pin, IVTV_REG_GPIO_OUT);
write_reg(itv->card->gpio_init.direction | pin, IVTV_REG_GPIO_DIR);
} }
static struct v4l2_queryctrl gpio_ctrl_mute = { static struct v4l2_queryctrl gpio_ctrl_mute = {
...@@ -173,17 +160,13 @@ static struct v4l2_queryctrl gpio_ctrl_mute = { ...@@ -173,17 +160,13 @@ static struct v4l2_queryctrl gpio_ctrl_mute = {
.flags = 0, .flags = 0,
}; };
int ivtv_gpio(struct ivtv *itv, unsigned int command, void *arg) static int subdev_s_clock_freq(struct v4l2_subdev *sd, u32 freq)
{ {
struct v4l2_tuner *tuner = arg; struct ivtv *itv = sd_to_ivtv(sd);
struct v4l2_control *ctrl = arg;
struct v4l2_routing *route = arg;
u16 mask, data; u16 mask, data;
switch (command) {
case VIDIOC_INT_AUDIO_CLOCK_FREQ:
mask = itv->card->gpio_audio_freq.mask; mask = itv->card->gpio_audio_freq.mask;
switch (*(u32 *)arg) { switch (freq) {
case 32000: case 32000:
data = itv->card->gpio_audio_freq.f32000; data = itv->card->gpio_audio_freq.f32000;
break; break;
...@@ -195,20 +178,32 @@ int ivtv_gpio(struct ivtv *itv, unsigned int command, void *arg) ...@@ -195,20 +178,32 @@ int ivtv_gpio(struct ivtv *itv, unsigned int command, void *arg)
data = itv->card->gpio_audio_freq.f48000; data = itv->card->gpio_audio_freq.f48000;
break; break;
} }
break; if (mask)
write_reg((read_reg(IVTV_REG_GPIO_OUT) & ~mask) | (data & mask), IVTV_REG_GPIO_OUT);
return 0;
}
static int subdev_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
{
struct ivtv *itv = sd_to_ivtv(sd);
u16 mask;
case VIDIOC_G_TUNER:
mask = itv->card->gpio_audio_detect.mask; mask = itv->card->gpio_audio_detect.mask;
if (mask == 0 || (read_reg(IVTV_REG_GPIO_IN) & mask)) if (mask == 0 || (read_reg(IVTV_REG_GPIO_IN) & mask))
tuner->rxsubchans = V4L2_TUNER_MODE_STEREO | vt->rxsubchans = V4L2_TUNER_MODE_STEREO |
V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2; V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2;
else else
tuner->rxsubchans = V4L2_TUNER_SUB_MONO; vt->rxsubchans = V4L2_TUNER_SUB_MONO;
return 0; return 0;
}
static int subdev_s_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
{
struct ivtv *itv = sd_to_ivtv(sd);
u16 mask, data;
case VIDIOC_S_TUNER:
mask = itv->card->gpio_audio_mode.mask; mask = itv->card->gpio_audio_mode.mask;
switch (tuner->audmode) { switch (vt->audmode) {
case V4L2_TUNER_MODE_LANG1: case V4L2_TUNER_MODE_LANG1:
data = itv->card->gpio_audio_mode.lang1; data = itv->card->gpio_audio_mode.lang1;
break; break;
...@@ -224,19 +219,40 @@ int ivtv_gpio(struct ivtv *itv, unsigned int command, void *arg) ...@@ -224,19 +219,40 @@ int ivtv_gpio(struct ivtv *itv, unsigned int command, void *arg)
data = itv->card->gpio_audio_mode.stereo; data = itv->card->gpio_audio_mode.stereo;
break; break;
} }
break; if (mask)
write_reg((read_reg(IVTV_REG_GPIO_OUT) & ~mask) | (data & mask), IVTV_REG_GPIO_OUT);
return 0;
}
static int subdev_s_radio(struct v4l2_subdev *sd)
{
struct ivtv *itv = sd_to_ivtv(sd);
u16 mask, data;
case AUDC_SET_RADIO:
mask = itv->card->gpio_audio_input.mask; mask = itv->card->gpio_audio_input.mask;
data = itv->card->gpio_audio_input.radio; data = itv->card->gpio_audio_input.radio;
break; if (mask)
write_reg((read_reg(IVTV_REG_GPIO_OUT) & ~mask) | (data & mask), IVTV_REG_GPIO_OUT);
return 0;
}
static int subdev_s_std(struct v4l2_subdev *sd, v4l2_std_id std)
{
struct ivtv *itv = sd_to_ivtv(sd);
u16 mask, data;
case VIDIOC_S_STD:
mask = itv->card->gpio_audio_input.mask; mask = itv->card->gpio_audio_input.mask;
data = itv->card->gpio_audio_input.tuner; data = itv->card->gpio_audio_input.tuner;
break; if (mask)
write_reg((read_reg(IVTV_REG_GPIO_OUT) & ~mask) | (data & mask), IVTV_REG_GPIO_OUT);
return 0;
}
static int subdev_s_audio_routing(struct v4l2_subdev *sd, const struct v4l2_routing *route)
{
struct ivtv *itv = sd_to_ivtv(sd);
u16 mask, data;
case VIDIOC_INT_S_AUDIO_ROUTING:
if (route->input > 2) if (route->input > 2)
return -EINVAL; return -EINVAL;
mask = itv->card->gpio_audio_input.mask; mask = itv->card->gpio_audio_input.mask;
...@@ -252,40 +268,61 @@ int ivtv_gpio(struct ivtv *itv, unsigned int command, void *arg) ...@@ -252,40 +268,61 @@ int ivtv_gpio(struct ivtv *itv, unsigned int command, void *arg)
data = itv->card->gpio_audio_input.radio; data = itv->card->gpio_audio_input.radio;
break; break;
} }
break; if (mask)
write_reg((read_reg(IVTV_REG_GPIO_OUT) & ~mask) | (data & mask), IVTV_REG_GPIO_OUT);
return 0;
}
static int subdev_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
{
struct ivtv *itv = sd_to_ivtv(sd);
u16 mask, data;
case VIDIOC_G_CTRL:
if (ctrl->id != V4L2_CID_AUDIO_MUTE) if (ctrl->id != V4L2_CID_AUDIO_MUTE)
return -EINVAL; return -EINVAL;
mask = itv->card->gpio_audio_mute.mask; mask = itv->card->gpio_audio_mute.mask;
data = itv->card->gpio_audio_mute.mute; data = itv->card->gpio_audio_mute.mute;
ctrl->value = (read_reg(IVTV_REG_GPIO_OUT) & mask) == data; ctrl->value = (read_reg(IVTV_REG_GPIO_OUT) & mask) == data;
return 0; return 0;
}
static int subdev_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
{
struct ivtv *itv = sd_to_ivtv(sd);
u16 mask, data;
case VIDIOC_S_CTRL:
if (ctrl->id != V4L2_CID_AUDIO_MUTE) if (ctrl->id != V4L2_CID_AUDIO_MUTE)
return -EINVAL; return -EINVAL;
mask = itv->card->gpio_audio_mute.mask; mask = itv->card->gpio_audio_mute.mask;
data = ctrl->value ? itv->card->gpio_audio_mute.mute : 0; data = ctrl->value ? itv->card->gpio_audio_mute.mute : 0;
break; if (mask)
write_reg((read_reg(IVTV_REG_GPIO_OUT) & ~mask) | (data & mask), IVTV_REG_GPIO_OUT);
case VIDIOC_QUERYCTRL: return 0;
{ }
struct v4l2_queryctrl *qc = arg;
static int subdev_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc)
{
if (qc->id != V4L2_CID_AUDIO_MUTE) if (qc->id != V4L2_CID_AUDIO_MUTE)
return -EINVAL; return -EINVAL;
*qc = gpio_ctrl_mute; *qc = gpio_ctrl_mute;
return 0; return 0;
} }
static int subdev_log_status(struct v4l2_subdev *sd)
{
struct ivtv *itv = sd_to_ivtv(sd);
case VIDIOC_LOG_STATUS:
IVTV_INFO("GPIO status: DIR=0x%04x OUT=0x%04x IN=0x%04x\n", IVTV_INFO("GPIO status: DIR=0x%04x OUT=0x%04x IN=0x%04x\n",
read_reg(IVTV_REG_GPIO_DIR), read_reg(IVTV_REG_GPIO_OUT), read_reg(IVTV_REG_GPIO_DIR), read_reg(IVTV_REG_GPIO_OUT),
read_reg(IVTV_REG_GPIO_IN)); read_reg(IVTV_REG_GPIO_IN));
return 0; return 0;
}
static int subdev_s_video_routing(struct v4l2_subdev *sd, const struct v4l2_routing *route)
{
struct ivtv *itv = sd_to_ivtv(sd);
u16 mask, data;
case VIDIOC_INT_S_VIDEO_ROUTING:
if (route->input > 2) /* 0:Tuner 1:Composite 2:S-Video */ if (route->input > 2) /* 0:Tuner 1:Composite 2:S-Video */
return -EINVAL; return -EINVAL;
mask = itv->card->gpio_video_input.mask; mask = itv->card->gpio_video_input.mask;
...@@ -295,12 +332,59 @@ int ivtv_gpio(struct ivtv *itv, unsigned int command, void *arg) ...@@ -295,12 +332,59 @@ int ivtv_gpio(struct ivtv *itv, unsigned int command, void *arg)
data = itv->card->gpio_video_input.composite; data = itv->card->gpio_video_input.composite;
else else
data = itv->card->gpio_video_input.svideo; data = itv->card->gpio_video_input.svideo;
break;
default:
return -EINVAL;
}
if (mask) if (mask)
write_reg((read_reg(IVTV_REG_GPIO_OUT) & ~mask) | (data & mask), IVTV_REG_GPIO_OUT); write_reg((read_reg(IVTV_REG_GPIO_OUT) & ~mask) | (data & mask), IVTV_REG_GPIO_OUT);
return 0; return 0;
} }
static const struct v4l2_subdev_core_ops subdev_core_ops = {
.log_status = subdev_log_status,
.g_ctrl = subdev_g_ctrl,
.s_ctrl = subdev_s_ctrl,
.queryctrl = subdev_queryctrl,
};
static const struct v4l2_subdev_tuner_ops subdev_tuner_ops = {
.s_std = subdev_s_std,
.s_radio = subdev_s_radio,
.g_tuner = subdev_g_tuner,
.s_tuner = subdev_s_tuner,
};
static const struct v4l2_subdev_audio_ops subdev_audio_ops = {
.s_clock_freq = subdev_s_clock_freq,
.s_routing = subdev_s_audio_routing,
};
static const struct v4l2_subdev_video_ops subdev_video_ops = {
.s_routing = subdev_s_video_routing,
};
static const struct v4l2_subdev_ops subdev_ops = {
.core = &subdev_core_ops,
.tuner = &subdev_tuner_ops,
.audio = &subdev_audio_ops,
.video = &subdev_video_ops,
};
int ivtv_gpio_init(struct ivtv *itv)
{
u16 pin = 0;
if (itv->card->xceive_pin)
pin = 1 << itv->card->xceive_pin;
if ((itv->card->gpio_init.direction | pin) == 0)
return 0;
IVTV_DEBUG_INFO("GPIO initial dir: %08x out: %08x\n",
read_reg(IVTV_REG_GPIO_DIR), read_reg(IVTV_REG_GPIO_OUT));
/* init output data then direction */
write_reg(itv->card->gpio_init.initial_value | pin, IVTV_REG_GPIO_OUT);
write_reg(itv->card->gpio_init.direction | pin, IVTV_REG_GPIO_DIR);
v4l2_subdev_init(&itv->sd_gpio, &subdev_ops);
snprintf(itv->sd_gpio.name, sizeof(itv->sd_gpio.name), "%s-gpio", itv->device.name);
itv->sd_gpio.grp_id = IVTV_HW_GPIO;
return v4l2_device_register_subdev(&itv->device, &itv->sd_gpio);
}
...@@ -22,9 +22,8 @@ ...@@ -22,9 +22,8 @@
#define IVTV_GPIO_H #define IVTV_GPIO_H
/* GPIO stuff */ /* GPIO stuff */
void ivtv_gpio_init(struct ivtv *itv); int ivtv_gpio_init(struct ivtv *itv);
void ivtv_reset_ir_gpio(struct ivtv *itv); void ivtv_reset_ir_gpio(struct ivtv *itv);
int ivtv_reset_tuner_gpio(void *dev, int component, int cmd, int value); int ivtv_reset_tuner_gpio(void *dev, int component, int cmd, int value);
int ivtv_gpio(struct ivtv *itv, unsigned int command, void *arg);
#endif #endif
This diff is collapsed.
...@@ -21,19 +21,8 @@ ...@@ -21,19 +21,8 @@
#ifndef IVTV_I2C_H #ifndef IVTV_I2C_H
#define IVTV_I2C_H #define IVTV_I2C_H
int ivtv_cx25840(struct ivtv *itv, unsigned int cmd, void *arg);
int ivtv_saa7115(struct ivtv *itv, unsigned int cmd, void *arg);
int ivtv_saa7127(struct ivtv *itv, unsigned int cmd, void *arg);
int ivtv_saa717x(struct ivtv *itv, unsigned int cmd, void *arg);
int ivtv_upd64031a(struct ivtv *itv, unsigned int cmd, void *arg);
int ivtv_upd64083(struct ivtv *itv, unsigned int cmd, void *arg);
int ivtv_i2c_hw_addr(struct ivtv *itv, u32 hw);
int ivtv_i2c_hw(struct ivtv *itv, u32 hw, unsigned int cmd, void *arg);
int ivtv_i2c_id(struct ivtv *itv, u32 id, unsigned int cmd, void *arg);
int ivtv_call_i2c_client(struct ivtv *itv, int addr, unsigned int cmd, void *arg);
void ivtv_call_i2c_clients(struct ivtv *itv, unsigned int cmd, void *arg);
int ivtv_i2c_register(struct ivtv *itv, unsigned idx); int ivtv_i2c_register(struct ivtv *itv, unsigned idx);
struct v4l2_subdev *ivtv_find_hw(struct ivtv *itv, u32 hw);
/* init + register i2c algo-bit adapter */ /* init + register i2c algo-bit adapter */
int init_ivtv_i2c(struct ivtv *itv); int init_ivtv_i2c(struct ivtv *itv);
......
...@@ -393,7 +393,7 @@ static int ivtv_g_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_fo ...@@ -393,7 +393,7 @@ static int ivtv_g_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_fo
return 0; return 0;
} }
itv->video_dec_func(itv, VIDIOC_G_FMT, fmt); v4l2_subdev_call(itv->sd_video, video, s_fmt, fmt);
vbifmt->service_set = ivtv_get_service_set(vbifmt); vbifmt->service_set = ivtv_get_service_set(vbifmt);
return 0; return 0;
} }
...@@ -581,7 +581,7 @@ static int ivtv_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f ...@@ -581,7 +581,7 @@ static int ivtv_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f
p->height = h; p->height = h;
if (p->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1) if (p->video_encoding == V4L2_MPEG_VIDEO_ENCODING_MPEG_1)
fmt->fmt.pix.width /= 2; fmt->fmt.pix.width /= 2;
itv->video_dec_func(itv, VIDIOC_S_FMT, fmt); v4l2_subdev_call(itv->sd_video, video, s_fmt, fmt);
return ivtv_g_fmt_vid_cap(file, fh, fmt); return ivtv_g_fmt_vid_cap(file, fh, fmt);
} }
...@@ -593,7 +593,7 @@ static int ivtv_s_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *f ...@@ -593,7 +593,7 @@ static int ivtv_s_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *f
return -EBUSY; return -EBUSY;
itv->vbi.sliced_in->service_set = 0; itv->vbi.sliced_in->service_set = 0;
itv->vbi.in.type = V4L2_BUF_TYPE_VBI_CAPTURE; itv->vbi.in.type = V4L2_BUF_TYPE_VBI_CAPTURE;
itv->video_dec_func(itv, VIDIOC_S_FMT, fmt); v4l2_subdev_call(itv->sd_video, video, s_fmt, fmt);
return ivtv_g_fmt_vbi_cap(file, fh, fmt); return ivtv_g_fmt_vbi_cap(file, fh, fmt);
} }
...@@ -611,7 +611,7 @@ static int ivtv_s_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_fo ...@@ -611,7 +611,7 @@ static int ivtv_s_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_fo
if (ivtv_raw_vbi(itv) && atomic_read(&itv->capturing) > 0) if (ivtv_raw_vbi(itv) && atomic_read(&itv->capturing) > 0)
return -EBUSY; return -EBUSY;
itv->vbi.in.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE; itv->vbi.in.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE;
itv->video_dec_func(itv, VIDIOC_S_FMT, fmt); v4l2_subdev_call(itv->sd_video, video, s_fmt, fmt);
memcpy(itv->vbi.sliced_in, vbifmt, sizeof(*itv->vbi.sliced_in)); memcpy(itv->vbi.sliced_in, vbifmt, sizeof(*itv->vbi.sliced_in));
return 0; return 0;
} }
...@@ -685,18 +685,17 @@ static int ivtv_g_chip_ident(struct file *file, void *fh, struct v4l2_chip_ident ...@@ -685,18 +685,17 @@ static int ivtv_g_chip_ident(struct file *file, void *fh, struct v4l2_chip_ident
chip->ident = itv->has_cx23415 ? V4L2_IDENT_CX23415 : V4L2_IDENT_CX23416; chip->ident = itv->has_cx23415 ? V4L2_IDENT_CX23415 : V4L2_IDENT_CX23416;
return 0; return 0;
} }
if (chip->match_type == V4L2_CHIP_MATCH_I2C_DRIVER) if (chip->match_type != V4L2_CHIP_MATCH_I2C_DRIVER &&
return ivtv_i2c_id(itv, chip->match_chip, VIDIOC_G_CHIP_IDENT, chip); chip->match_type != V4L2_CHIP_MATCH_I2C_ADDR)
if (chip->match_type == V4L2_CHIP_MATCH_I2C_ADDR)
return ivtv_call_i2c_client(itv, chip->match_chip, VIDIOC_G_CHIP_IDENT, chip);
return -EINVAL; return -EINVAL;
/* TODO: is this correct? */
return ivtv_call_all_err(itv, core, g_chip_ident, chip);
} }
#ifdef CONFIG_VIDEO_ADV_DEBUG #ifdef CONFIG_VIDEO_ADV_DEBUG
static int ivtv_itvc(struct ivtv *itv, unsigned int cmd, void *arg) static int ivtv_itvc(struct ivtv *itv, unsigned int cmd, void *arg)
{ {
struct v4l2_register *regs = arg; struct v4l2_register *regs = arg;
unsigned long flags;
volatile u8 __iomem *reg_start; volatile u8 __iomem *reg_start;
if (!capable(CAP_SYS_ADMIN)) if (!capable(CAP_SYS_ADMIN))
...@@ -711,12 +710,10 @@ static int ivtv_itvc(struct ivtv *itv, unsigned int cmd, void *arg) ...@@ -711,12 +710,10 @@ static int ivtv_itvc(struct ivtv *itv, unsigned int cmd, void *arg)
else else
return -EINVAL; return -EINVAL;
spin_lock_irqsave(&ivtv_cards_lock, flags);
if (cmd == VIDIOC_DBG_G_REGISTER) if (cmd == VIDIOC_DBG_G_REGISTER)
regs->val = readl(regs->reg + reg_start); regs->val = readl(regs->reg + reg_start);
else else
writel(regs->val, regs->reg + reg_start); writel(regs->val, regs->reg + reg_start);
spin_unlock_irqrestore(&ivtv_cards_lock, flags);
return 0; return 0;
} }
...@@ -726,9 +723,10 @@ static int ivtv_g_register(struct file *file, void *fh, struct v4l2_register *re ...@@ -726,9 +723,10 @@ static int ivtv_g_register(struct file *file, void *fh, struct v4l2_register *re
if (v4l2_chip_match_host(reg->match_type, reg->match_chip)) if (v4l2_chip_match_host(reg->match_type, reg->match_chip))
return ivtv_itvc(itv, VIDIOC_DBG_G_REGISTER, reg); return ivtv_itvc(itv, VIDIOC_DBG_G_REGISTER, reg);
if (reg->match_type == V4L2_CHIP_MATCH_I2C_DRIVER) /* TODO: subdev errors should not be ignored, this should become a
return ivtv_i2c_id(itv, reg->match_chip, VIDIOC_DBG_G_REGISTER, reg); subdev helper function. */
return ivtv_call_i2c_client(itv, reg->match_chip, VIDIOC_DBG_G_REGISTER, reg); ivtv_call_all(itv, core, g_register, reg);
return 0;
} }
static int ivtv_s_register(struct file *file, void *fh, struct v4l2_register *reg) static int ivtv_s_register(struct file *file, void *fh, struct v4l2_register *reg)
...@@ -737,9 +735,10 @@ static int ivtv_s_register(struct file *file, void *fh, struct v4l2_register *re ...@@ -737,9 +735,10 @@ static int ivtv_s_register(struct file *file, void *fh, struct v4l2_register *re
if (v4l2_chip_match_host(reg->match_type, reg->match_chip)) if (v4l2_chip_match_host(reg->match_type, reg->match_chip))
return ivtv_itvc(itv, VIDIOC_DBG_S_REGISTER, reg); return ivtv_itvc(itv, VIDIOC_DBG_S_REGISTER, reg);
if (reg->match_type == V4L2_CHIP_MATCH_I2C_DRIVER) /* TODO: subdev errors should not be ignored, this should become a
return ivtv_i2c_id(itv, reg->match_chip, VIDIOC_DBG_S_REGISTER, reg); subdev helper function. */
return ivtv_call_i2c_client(itv, reg->match_chip, VIDIOC_DBG_S_REGISTER, reg); ivtv_call_all(itv, core, s_register, reg);
return 0;
} }
#endif #endif
...@@ -884,12 +883,6 @@ static int ivtv_s_crop(struct file *file, void *fh, struct v4l2_crop *crop) ...@@ -884,12 +883,6 @@ static int ivtv_s_crop(struct file *file, void *fh, struct v4l2_crop *crop)
streamtype = id->type; streamtype = id->type;
if (ivtv_debug & IVTV_DBGFLG_IOCTL) {
printk(KERN_INFO "ivtv%d ioctl: ", itv->num);
/* Should be replaced */
/* v4l_printk_ioctl(VIDIOC_S_CROP); */
}
if (crop->type == V4L2_BUF_TYPE_VIDEO_OUTPUT && if (crop->type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) { (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) {
if (streamtype == IVTV_DEC_STREAM_TYPE_YUV) { if (streamtype == IVTV_DEC_STREAM_TYPE_YUV) {
...@@ -1050,7 +1043,7 @@ static int ivtv_s_output(struct file *file, void *fh, unsigned int outp) ...@@ -1050,7 +1043,7 @@ static int ivtv_s_output(struct file *file, void *fh, unsigned int outp)
itv->active_output = outp; itv->active_output = outp;
route.input = SAA7127_INPUT_TYPE_NORMAL; route.input = SAA7127_INPUT_TYPE_NORMAL;
route.output = itv->card->video_outputs[outp].video_output; route.output = itv->card->video_outputs[outp].video_output;
ivtv_saa7127(itv, VIDIOC_INT_S_VIDEO_ROUTING, &route); ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_routing, &route);
return 0; return 0;
} }
...@@ -1062,7 +1055,7 @@ static int ivtv_g_frequency(struct file *file, void *fh, struct v4l2_frequency * ...@@ -1062,7 +1055,7 @@ static int ivtv_g_frequency(struct file *file, void *fh, struct v4l2_frequency *
if (vf->tuner != 0) if (vf->tuner != 0)
return -EINVAL; return -EINVAL;
ivtv_call_i2c_clients(itv, VIDIOC_G_FREQUENCY, vf); ivtv_call_all(itv, tuner, g_frequency, vf);
return 0; return 0;
} }
...@@ -1075,7 +1068,7 @@ int ivtv_s_frequency(struct file *file, void *fh, struct v4l2_frequency *vf) ...@@ -1075,7 +1068,7 @@ int ivtv_s_frequency(struct file *file, void *fh, struct v4l2_frequency *vf)
ivtv_mute(itv); ivtv_mute(itv);
IVTV_DEBUG_INFO("v4l2 ioctl: set frequency %d\n", vf->frequency); IVTV_DEBUG_INFO("v4l2 ioctl: set frequency %d\n", vf->frequency);
ivtv_call_i2c_clients(itv, VIDIOC_S_FREQUENCY, vf); ivtv_call_all(itv, tuner, s_frequency, vf);
ivtv_unmute(itv); ivtv_unmute(itv);
return 0; return 0;
} }
...@@ -1123,14 +1116,14 @@ int ivtv_s_std(struct file *file, void *fh, v4l2_std_id *std) ...@@ -1123,14 +1116,14 @@ int ivtv_s_std(struct file *file, void *fh, v4l2_std_id *std)
IVTV_DEBUG_INFO("Switching standard to %llx.\n", (unsigned long long)itv->std); IVTV_DEBUG_INFO("Switching standard to %llx.\n", (unsigned long long)itv->std);
/* Tuner */ /* Tuner */
ivtv_call_i2c_clients(itv, VIDIOC_S_STD, &itv->std); ivtv_call_all(itv, tuner, s_std, itv->std);
if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) { if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) {
/* set display standard */ /* set display standard */
itv->std_out = *std; itv->std_out = *std;
itv->is_out_60hz = itv->is_60hz; itv->is_out_60hz = itv->is_60hz;
itv->is_out_50hz = itv->is_50hz; itv->is_out_50hz = itv->is_50hz;
ivtv_call_i2c_clients(itv, VIDIOC_INT_S_STD_OUTPUT, &itv->std_out); ivtv_call_all(itv, video, s_std_output, itv->std_out);
ivtv_vapi(itv, CX2341X_DEC_SET_STANDARD, 1, itv->is_out_50hz); ivtv_vapi(itv, CX2341X_DEC_SET_STANDARD, 1, itv->is_out_50hz);
itv->main_rect.left = itv->main_rect.top = 0; itv->main_rect.left = itv->main_rect.top = 0;
itv->main_rect.width = 720; itv->main_rect.width = 720;
...@@ -1154,7 +1147,7 @@ static int ivtv_s_tuner(struct file *file, void *fh, struct v4l2_tuner *vt) ...@@ -1154,7 +1147,7 @@ static int ivtv_s_tuner(struct file *file, void *fh, struct v4l2_tuner *vt)
if (vt->index != 0) if (vt->index != 0)
return -EINVAL; return -EINVAL;
ivtv_call_i2c_clients(itv, VIDIOC_S_TUNER, vt); ivtv_call_all(itv, tuner, s_tuner, vt);
return 0; return 0;
} }
...@@ -1166,7 +1159,7 @@ static int ivtv_g_tuner(struct file *file, void *fh, struct v4l2_tuner *vt) ...@@ -1166,7 +1159,7 @@ static int ivtv_g_tuner(struct file *file, void *fh, struct v4l2_tuner *vt)
if (vt->index != 0) if (vt->index != 0)
return -EINVAL; return -EINVAL;
ivtv_call_i2c_clients(itv, VIDIOC_G_TUNER, vt); ivtv_call_all(itv, tuner, g_tuner, vt);
if (test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags)) { if (test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags)) {
strlcpy(vt->name, "ivtv Radio Tuner", sizeof(vt->name)); strlcpy(vt->name, "ivtv Radio Tuner", sizeof(vt->name));
...@@ -1444,14 +1437,15 @@ static int ivtv_log_status(struct file *file, void *fh) ...@@ -1444,14 +1437,15 @@ static int ivtv_log_status(struct file *file, void *fh)
struct v4l2_audio audin; struct v4l2_audio audin;
int i; int i;
IVTV_INFO("================= START STATUS CARD #%d =================\n", itv->num); IVTV_INFO("================= START STATUS CARD #%d =================\n",
itv->instance);
IVTV_INFO("Version: %s Card: %s\n", IVTV_VERSION, itv->card_name); IVTV_INFO("Version: %s Card: %s\n", IVTV_VERSION, itv->card_name);
if (itv->hw_flags & IVTV_HW_TVEEPROM) { if (itv->hw_flags & IVTV_HW_TVEEPROM) {
struct tveeprom tv; struct tveeprom tv;
ivtv_read_eeprom(itv, &tv); ivtv_read_eeprom(itv, &tv);
} }
ivtv_call_i2c_clients(itv, VIDIOC_LOG_STATUS, NULL); ivtv_call_all(itv, core, log_status);
ivtv_get_input(itv, itv->active_input, &vidin); ivtv_get_input(itv, itv->active_input, &vidin);
ivtv_get_audio_input(itv, itv->audio_input, &audin); ivtv_get_audio_input(itv, itv->audio_input, &audin);
IVTV_INFO("Video Input: %s\n", vidin.name); IVTV_INFO("Video Input: %s\n", vidin.name);
...@@ -1518,7 +1512,7 @@ static int ivtv_log_status(struct file *file, void *fh) ...@@ -1518,7 +1512,7 @@ static int ivtv_log_status(struct file *file, void *fh)
} }
IVTV_INFO("Tuner: %s\n", IVTV_INFO("Tuner: %s\n",
test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags) ? "Radio" : "TV"); test_bit(IVTV_F_I_RADIO_USER, &itv->i_flags) ? "Radio" : "TV");
cx2341x_log_status(&itv->params, itv->name); cx2341x_log_status(&itv->params, itv->device.name);
IVTV_INFO("Status flags: 0x%08lx\n", itv->i_flags); IVTV_INFO("Status flags: 0x%08lx\n", itv->i_flags);
for (i = 0; i < IVTV_MAX_STREAMS; i++) { for (i = 0; i < IVTV_MAX_STREAMS; i++) {
struct ivtv_stream *s = &itv->streams[i]; struct ivtv_stream *s = &itv->streams[i];
...@@ -1530,8 +1524,11 @@ static int ivtv_log_status(struct file *file, void *fh) ...@@ -1530,8 +1524,11 @@ static int ivtv_log_status(struct file *file, void *fh)
(s->buffers * s->buf_size) / 1024, s->buffers); (s->buffers * s->buf_size) / 1024, s->buffers);
} }
IVTV_INFO("Read MPG/VBI: %lld/%lld bytes\n", (long long)itv->mpg_data_received, (long long)itv->vbi_data_inserted); IVTV_INFO("Read MPG/VBI: %lld/%lld bytes\n",
IVTV_INFO("================== END STATUS CARD #%d ==================\n", itv->num); (long long)itv->mpg_data_received,
(long long)itv->vbi_data_inserted);
IVTV_INFO("================== END STATUS CARD #%d ==================\n",
itv->instance);
return 0; return 0;
} }
...@@ -1736,7 +1733,7 @@ static int ivtv_default(struct file *file, void *fh, int cmd, void *arg) ...@@ -1736,7 +1733,7 @@ static int ivtv_default(struct file *file, void *fh, int cmd, void *arg)
case VIDIOC_INT_S_AUDIO_ROUTING: { case VIDIOC_INT_S_AUDIO_ROUTING: {
struct v4l2_routing *route = arg; struct v4l2_routing *route = arg;
ivtv_i2c_hw(itv, itv->card->hw_audio, VIDIOC_INT_S_AUDIO_ROUTING, route); ivtv_call_hw(itv, itv->card->hw_audio, audio, s_routing, route);
break; break;
} }
...@@ -1746,7 +1743,7 @@ static int ivtv_default(struct file *file, void *fh, int cmd, void *arg) ...@@ -1746,7 +1743,7 @@ static int ivtv_default(struct file *file, void *fh, int cmd, void *arg)
if ((val == 0 && itv->options.newi2c) || (val & 0x01)) if ((val == 0 && itv->options.newi2c) || (val & 0x01))
ivtv_reset_ir_gpio(itv); ivtv_reset_ir_gpio(itv);
if (val & 0x02) if (val & 0x02)
itv->video_dec_func(itv, cmd, NULL); v4l2_subdev_call(itv->sd_video, core, reset, 0);
break; break;
} }
......
...@@ -47,13 +47,13 @@ void ivtv_audio_set_io(struct ivtv *itv) ...@@ -47,13 +47,13 @@ void ivtv_audio_set_io(struct ivtv *itv)
route.output = 0; route.output = 0;
if (itv->card->hw_muxer & IVTV_HW_M52790) if (itv->card->hw_muxer & IVTV_HW_M52790)
route.output = M52790_OUT_STEREO; route.output = M52790_OUT_STEREO;
ivtv_i2c_hw(itv, itv->card->hw_muxer, VIDIOC_INT_S_AUDIO_ROUTING, &route); v4l2_subdev_call(itv->sd_muxer, audio, s_routing, &route);
route.input = in->audio_input; route.input = in->audio_input;
route.output = 0; route.output = 0;
if (itv->card->hw_audio & IVTV_HW_MSP34XX) if (itv->card->hw_audio & IVTV_HW_MSP34XX)
route.output = MSP_OUTPUT(MSP_SC_IN_DSP_SCART1); route.output = MSP_OUTPUT(MSP_SC_IN_DSP_SCART1);
ivtv_i2c_hw(itv, itv->card->hw_audio, VIDIOC_INT_S_AUDIO_ROUTING, &route); ivtv_call_hw(itv, itv->card->hw_audio, audio, s_routing, &route);
} }
/* Selects the video input and output according to the current /* Selects the video input and output according to the current
...@@ -66,7 +66,7 @@ void ivtv_video_set_io(struct ivtv *itv) ...@@ -66,7 +66,7 @@ void ivtv_video_set_io(struct ivtv *itv)
route.input = itv->card->video_inputs[inp].video_input; route.input = itv->card->video_inputs[inp].video_input;
route.output = 0; route.output = 0;
itv->video_dec_func(itv, VIDIOC_INT_S_VIDEO_ROUTING, &route); v4l2_subdev_call(itv->sd_video, video, s_routing, &route);
type = itv->card->video_inputs[inp].video_type; type = itv->card->video_inputs[inp].video_type;
...@@ -79,7 +79,7 @@ void ivtv_video_set_io(struct ivtv *itv) ...@@ -79,7 +79,7 @@ void ivtv_video_set_io(struct ivtv *itv)
} }
if (itv->card->hw_video & IVTV_HW_GPIO) if (itv->card->hw_video & IVTV_HW_GPIO)
ivtv_gpio(itv, VIDIOC_INT_S_VIDEO_ROUTING, &route); ivtv_call_hw(itv, IVTV_HW_GPIO, video, s_routing, &route);
if (itv->card->hw_video & IVTV_HW_UPD64031A) { if (itv->card->hw_video & IVTV_HW_UPD64031A) {
if (type == IVTV_CARD_INPUT_VID_TUNER || if (type == IVTV_CARD_INPUT_VID_TUNER ||
...@@ -92,7 +92,7 @@ void ivtv_video_set_io(struct ivtv *itv) ...@@ -92,7 +92,7 @@ void ivtv_video_set_io(struct ivtv *itv)
} }
route.input |= itv->card->gr_config; route.input |= itv->card->gr_config;
ivtv_upd64031a(itv, VIDIOC_INT_S_VIDEO_ROUTING, &route); ivtv_call_hw(itv, IVTV_HW_UPD64031A, video, s_routing, &route);
} }
if (itv->card->hw_video & IVTV_HW_UPD6408X) { if (itv->card->hw_video & IVTV_HW_UPD6408X) {
...@@ -110,6 +110,6 @@ void ivtv_video_set_io(struct ivtv *itv) ...@@ -110,6 +110,6 @@ void ivtv_video_set_io(struct ivtv *itv)
route.input |= UPD64083_EXT_Y_ADC; route.input |= UPD64083_EXT_Y_ADC;
} }
} }
ivtv_upd64083(itv, VIDIOC_INT_S_VIDEO_ROUTING, &route); ivtv_call_hw(itv, IVTV_HW_UPD6408X, video, s_routing, &route);
} }
} }
...@@ -172,7 +172,7 @@ static int ivtv_prep_dev(struct ivtv *itv, int type) ...@@ -172,7 +172,7 @@ static int ivtv_prep_dev(struct ivtv *itv, int type)
{ {
struct ivtv_stream *s = &itv->streams[type]; struct ivtv_stream *s = &itv->streams[type];
int num_offset = ivtv_stream_info[type].num_offset; int num_offset = ivtv_stream_info[type].num_offset;
int num = itv->num + ivtv_first_minor + num_offset; int num = itv->instance + ivtv_first_minor + num_offset;
/* These four fields are always initialized. If v4l2dev == NULL, then /* These four fields are always initialized. If v4l2dev == NULL, then
this stream is not in use. In that case no other fields but these this stream is not in use. In that case no other fields but these
...@@ -205,8 +205,8 @@ static int ivtv_prep_dev(struct ivtv *itv, int type) ...@@ -205,8 +205,8 @@ static int ivtv_prep_dev(struct ivtv *itv, int type)
return -ENOMEM; return -ENOMEM;
} }
snprintf(s->v4l2dev->name, sizeof(s->v4l2dev->name), "ivtv%d %s", snprintf(s->v4l2dev->name, sizeof(s->v4l2dev->name), "%s %s",
itv->num, s->name); itv->device.name, s->name);
s->v4l2dev->num = num; s->v4l2dev->num = num;
s->v4l2dev->parent = &itv->dev->dev; s->v4l2dev->parent = &itv->dev->dev;
...@@ -260,6 +260,7 @@ static int ivtv_reg_dev(struct ivtv *itv, int type) ...@@ -260,6 +260,7 @@ static int ivtv_reg_dev(struct ivtv *itv, int type)
if (s_mpg->v4l2dev) if (s_mpg->v4l2dev)
num = s_mpg->v4l2dev->num + ivtv_stream_info[type].num_offset; num = s_mpg->v4l2dev->num + ivtv_stream_info[type].num_offset;
} }
video_set_drvdata(s->v4l2dev, s);
/* Register device. First try the desired minor, then any free one. */ /* Register device. First try the desired minor, then any free one. */
if (video_register_device(s->v4l2dev, vfl_type, num)) { if (video_register_device(s->v4l2dev, vfl_type, num)) {
...@@ -343,7 +344,7 @@ static void ivtv_vbi_setup(struct ivtv *itv) ...@@ -343,7 +344,7 @@ static void ivtv_vbi_setup(struct ivtv *itv)
ivtv_vapi(itv, CX2341X_ENC_SET_VBI_LINE, 5, 0xffff , 0, 0, 0, 0); ivtv_vapi(itv, CX2341X_ENC_SET_VBI_LINE, 5, 0xffff , 0, 0, 0, 0);
/* setup VBI registers */ /* setup VBI registers */
itv->video_dec_func(itv, VIDIOC_S_FMT, &itv->vbi.in); v4l2_subdev_call(itv->sd_video, video, s_fmt, &itv->vbi.in);
/* determine number of lines and total number of VBI bytes. /* determine number of lines and total number of VBI bytes.
A raw line takes 1443 bytes: 2 * 720 + 4 byte frame header - 1 A raw line takes 1443 bytes: 2 * 720 + 4 byte frame header - 1
...@@ -577,10 +578,10 @@ int ivtv_start_v4l2_encode_stream(struct ivtv_stream *s) ...@@ -577,10 +578,10 @@ int ivtv_start_v4l2_encode_stream(struct ivtv_stream *s)
clear_bit(IVTV_F_I_EOS, &itv->i_flags); clear_bit(IVTV_F_I_EOS, &itv->i_flags);
/* Initialize Digitizer for Capture */ /* Initialize Digitizer for Capture */
itv->video_dec_func(itv, VIDIOC_STREAMOFF, NULL); v4l2_subdev_call(itv->sd_video, video, s_stream, 0);
ivtv_msleep_timeout(300, 1); ivtv_msleep_timeout(300, 1);
ivtv_vapi(itv, CX2341X_ENC_INITIALIZE_INPUT, 0); ivtv_vapi(itv, CX2341X_ENC_INITIALIZE_INPUT, 0);
itv->video_dec_func(itv, VIDIOC_STREAMON, NULL); v4l2_subdev_call(itv->sd_video, video, s_stream, 1);
} }
/* begin_capture */ /* begin_capture */
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include "ivtv-i2c.h" #include "ivtv-i2c.h"
#include "ivtv-ioctl.h" #include "ivtv-ioctl.h"
#include "ivtv-queue.h" #include "ivtv-queue.h"
#include "ivtv-cards.h"
#include "ivtv-vbi.h" #include "ivtv-vbi.h"
static void ivtv_set_vps(struct ivtv *itv, int enabled) static void ivtv_set_vps(struct ivtv *itv, int enabled)
...@@ -37,7 +38,7 @@ static void ivtv_set_vps(struct ivtv *itv, int enabled) ...@@ -37,7 +38,7 @@ static void ivtv_set_vps(struct ivtv *itv, int enabled)
data.data[9] = itv->vbi.vps_payload.data[2]; data.data[9] = itv->vbi.vps_payload.data[2];
data.data[10] = itv->vbi.vps_payload.data[3]; data.data[10] = itv->vbi.vps_payload.data[3];
data.data[11] = itv->vbi.vps_payload.data[4]; data.data[11] = itv->vbi.vps_payload.data[4];
ivtv_saa7127(itv, VIDIOC_INT_S_VBI_DATA, &data); ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_vbi_data, &data);
} }
static void ivtv_set_cc(struct ivtv *itv, int mode, const struct vbi_cc *cc) static void ivtv_set_cc(struct ivtv *itv, int mode, const struct vbi_cc *cc)
...@@ -51,12 +52,12 @@ static void ivtv_set_cc(struct ivtv *itv, int mode, const struct vbi_cc *cc) ...@@ -51,12 +52,12 @@ static void ivtv_set_cc(struct ivtv *itv, int mode, const struct vbi_cc *cc)
data.line = (mode & 1) ? 21 : 0; data.line = (mode & 1) ? 21 : 0;
data.data[0] = cc->odd[0]; data.data[0] = cc->odd[0];
data.data[1] = cc->odd[1]; data.data[1] = cc->odd[1];
ivtv_saa7127(itv, VIDIOC_INT_S_VBI_DATA, &data); ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_vbi_data, &data);
data.field = 1; data.field = 1;
data.line = (mode & 2) ? 21 : 0; data.line = (mode & 2) ? 21 : 0;
data.data[0] = cc->even[0]; data.data[0] = cc->even[0];
data.data[1] = cc->even[1]; data.data[1] = cc->even[1];
ivtv_saa7127(itv, VIDIOC_INT_S_VBI_DATA, &data); ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_vbi_data, &data);
} }
static void ivtv_set_wss(struct ivtv *itv, int enabled, int mode) static void ivtv_set_wss(struct ivtv *itv, int enabled, int mode)
...@@ -79,7 +80,7 @@ static void ivtv_set_wss(struct ivtv *itv, int enabled, int mode) ...@@ -79,7 +80,7 @@ static void ivtv_set_wss(struct ivtv *itv, int enabled, int mode)
data.line = enabled ? 23 : 0; data.line = enabled ? 23 : 0;
data.data[0] = mode & 0xff; data.data[0] = mode & 0xff;
data.data[1] = (mode >> 8) & 0xff; data.data[1] = (mode >> 8) & 0xff;
ivtv_saa7127(itv, VIDIOC_INT_S_VBI_DATA, &data); ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_vbi_data, &data);
} }
static int odd_parity(u8 c) static int odd_parity(u8 c)
...@@ -313,7 +314,7 @@ static u32 compress_sliced_buf(struct ivtv *itv, u32 line, u8 *buf, u32 size, u8 ...@@ -313,7 +314,7 @@ static u32 compress_sliced_buf(struct ivtv *itv, u32 line, u8 *buf, u32 size, u8
continue; continue;
} }
vbi.p = p + 4; vbi.p = p + 4;
itv->video_dec_func(itv, VIDIOC_INT_DECODE_VBI_LINE, &vbi); v4l2_subdev_call(itv->sd_video, video, decode_vbi_line, &vbi);
if (vbi.type && !(lines & (1 << vbi.line))) { if (vbi.type && !(lines & (1 << vbi.line))) {
lines |= 1 << vbi.line; lines |= 1 << vbi.line;
itv->vbi.sliced_data[line].id = vbi.type; itv->vbi.sliced_data[line].id = vbi.type;
...@@ -437,7 +438,7 @@ void ivtv_vbi_work_handler(struct ivtv *itv) ...@@ -437,7 +438,7 @@ void ivtv_vbi_work_handler(struct ivtv *itv)
data.id = V4L2_SLICED_WSS_625; data.id = V4L2_SLICED_WSS_625;
data.field = 0; data.field = 0;
if (itv->video_dec_func(itv, VIDIOC_INT_G_VBI_DATA, &data) == 0) { if (v4l2_subdev_call(itv->sd_video, video, g_vbi_data, &data) == 0) {
ivtv_set_wss(itv, 1, data.data[0] & 0xf); ivtv_set_wss(itv, 1, data.data[0] & 0xf);
vi->wss_missing_cnt = 0; vi->wss_missing_cnt = 0;
} else if (vi->wss_missing_cnt == 4) { } else if (vi->wss_missing_cnt == 4) {
...@@ -451,13 +452,13 @@ void ivtv_vbi_work_handler(struct ivtv *itv) ...@@ -451,13 +452,13 @@ void ivtv_vbi_work_handler(struct ivtv *itv)
data.id = V4L2_SLICED_CAPTION_525; data.id = V4L2_SLICED_CAPTION_525;
data.field = 0; data.field = 0;
if (itv->video_dec_func(itv, VIDIOC_INT_G_VBI_DATA, &data) == 0) { if (v4l2_subdev_call(itv->sd_video, video, g_vbi_data, &data) == 0) {
mode |= 1; mode |= 1;
cc.odd[0] = data.data[0]; cc.odd[0] = data.data[0];
cc.odd[1] = data.data[1]; cc.odd[1] = data.data[1];
} }
data.field = 1; data.field = 1;
if (itv->video_dec_func(itv, VIDIOC_INT_G_VBI_DATA, &data) == 0) { if (v4l2_subdev_call(itv->sd_video, video, g_vbi_data, &data) == 0) {
mode |= 2; mode |= 2;
cc.even[0] = data.data[0]; cc.even[0] = data.data[0];
cc.even[1] = data.data[1]; cc.even[1] = data.data[1];
......
...@@ -48,6 +48,7 @@ ...@@ -48,6 +48,7 @@
#endif #endif
#include "ivtv-driver.h" #include "ivtv-driver.h"
#include "ivtv-cards.h"
#include "ivtv-i2c.h" #include "ivtv-i2c.h"
#include "ivtv-udma.h" #include "ivtv-udma.h"
#include "ivtv-mailbox.h" #include "ivtv-mailbox.h"
...@@ -121,15 +122,15 @@ MODULE_LICENSE("GPL"); ...@@ -121,15 +122,15 @@ MODULE_LICENSE("GPL");
#define IVTVFB_DEBUG(x, type, fmt, args...) \ #define IVTVFB_DEBUG(x, type, fmt, args...) \
do { \ do { \
if ((x) & ivtvfb_debug) \ if ((x) & ivtvfb_debug) \
printk(KERN_INFO "ivtvfb%d " type ": " fmt, itv->num , ## args); \ printk(KERN_INFO "ivtvfb%d " type ": " fmt, itv->instance , ## args); \
} while (0) } while (0)
#define IVTVFB_DEBUG_WARN(fmt, args...) IVTVFB_DEBUG(IVTVFB_DBGFLG_WARN, "warning", fmt , ## args) #define IVTVFB_DEBUG_WARN(fmt, args...) IVTVFB_DEBUG(IVTVFB_DBGFLG_WARN, "warning", fmt , ## args)
#define IVTVFB_DEBUG_INFO(fmt, args...) IVTVFB_DEBUG(IVTVFB_DBGFLG_INFO, "info", fmt , ## args) #define IVTVFB_DEBUG_INFO(fmt, args...) IVTVFB_DEBUG(IVTVFB_DBGFLG_INFO, "info", fmt , ## args)
/* Standard kernel messages */ /* Standard kernel messages */
#define IVTVFB_ERR(fmt, args...) printk(KERN_ERR "ivtvfb%d: " fmt, itv->num , ## args) #define IVTVFB_ERR(fmt, args...) printk(KERN_ERR "ivtvfb%d: " fmt, itv->instance , ## args)
#define IVTVFB_WARN(fmt, args...) printk(KERN_WARNING "ivtvfb%d: " fmt, itv->num , ## args) #define IVTVFB_WARN(fmt, args...) printk(KERN_WARNING "ivtvfb%d: " fmt, itv->instance , ## args)
#define IVTVFB_INFO(fmt, args...) printk(KERN_INFO "ivtvfb%d: " fmt, itv->num , ## args) #define IVTVFB_INFO(fmt, args...) printk(KERN_INFO "ivtvfb%d: " fmt, itv->instance , ## args)
/* --------------------------------------------------------------------- */ /* --------------------------------------------------------------------- */
...@@ -895,16 +896,16 @@ static int ivtvfb_blank(int blank_mode, struct fb_info *info) ...@@ -895,16 +896,16 @@ static int ivtvfb_blank(int blank_mode, struct fb_info *info)
switch (blank_mode) { switch (blank_mode) {
case FB_BLANK_UNBLANK: case FB_BLANK_UNBLANK:
ivtv_vapi(itv, CX2341X_OSD_SET_STATE, 1, 1); ivtv_vapi(itv, CX2341X_OSD_SET_STATE, 1, 1);
ivtv_saa7127(itv, VIDIOC_STREAMON, NULL); ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_stream, 1);
break; break;
case FB_BLANK_NORMAL: case FB_BLANK_NORMAL:
case FB_BLANK_HSYNC_SUSPEND: case FB_BLANK_HSYNC_SUSPEND:
case FB_BLANK_VSYNC_SUSPEND: case FB_BLANK_VSYNC_SUSPEND:
ivtv_vapi(itv, CX2341X_OSD_SET_STATE, 1, 0); ivtv_vapi(itv, CX2341X_OSD_SET_STATE, 1, 0);
ivtv_saa7127(itv, VIDIOC_STREAMON, NULL); ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_stream, 1);
break; break;
case FB_BLANK_POWERDOWN: case FB_BLANK_POWERDOWN:
ivtv_saa7127(itv, VIDIOC_STREAMOFF, NULL); ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_stream, 0);
ivtv_vapi(itv, CX2341X_OSD_SET_STATE, 1, 0); ivtv_vapi(itv, CX2341X_OSD_SET_STATE, 1, 0);
break; break;
} }
...@@ -1188,10 +1189,45 @@ static int ivtvfb_init_card(struct ivtv *itv) ...@@ -1188,10 +1189,45 @@ static int ivtvfb_init_card(struct ivtv *itv)
} }
static int __init ivtvfb_callback_init(struct device *dev, void *p)
{
struct v4l2_device *v4l2_dev = dev_get_drvdata(dev);
struct ivtv *itv = container_of(v4l2_dev, struct ivtv, device);
if (itv && (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) {
if (ivtvfb_init_card(itv) == 0) {
IVTVFB_INFO("Framebuffer registered on %s\n",
itv->device.name);
(*(int *)p)++;
}
}
return 0;
}
static int ivtvfb_callback_cleanup(struct device *dev, void *p)
{
struct v4l2_device *v4l2_dev = dev_get_drvdata(dev);
struct ivtv *itv = container_of(v4l2_dev, struct ivtv, device);
if (itv && (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) {
if (unregister_framebuffer(&itv->osd_info->ivtvfb_info)) {
IVTVFB_WARN("Framebuffer %d is in use, cannot unload\n",
itv->instance);
return 0;
}
IVTVFB_INFO("Unregister framebuffer %d\n", itv->instance);
ivtvfb_blank(FB_BLANK_POWERDOWN, &itv->osd_info->ivtvfb_info);
ivtvfb_release_buffers(itv);
itv->osd_video_pbase = 0;
}
return 0;
}
static int __init ivtvfb_init(void) static int __init ivtvfb_init(void)
{ {
struct ivtv *itv; struct device_driver *drv;
int i, registered = 0; int registered = 0;
int err;
if (ivtvfb_card_id < -1 || ivtvfb_card_id >= IVTV_MAX_CARDS) { if (ivtvfb_card_id < -1 || ivtvfb_card_id >= IVTV_MAX_CARDS) {
printk(KERN_ERR "ivtvfb: ivtvfb_card_id parameter is out of range (valid range: -1 - %d)\n", printk(KERN_ERR "ivtvfb: ivtvfb_card_id parameter is out of range (valid range: -1 - %d)\n",
...@@ -1199,20 +1235,11 @@ static int __init ivtvfb_init(void) ...@@ -1199,20 +1235,11 @@ static int __init ivtvfb_init(void)
return -EINVAL; return -EINVAL;
} }
/* Locate & initialise all cards supporting an OSD. */ drv = driver_find("ivtv", &pci_bus_type);
for (i = 0; i < ivtv_cards_active; i++) { err = driver_for_each_device(drv, NULL, &registered, ivtvfb_callback_init);
if (ivtvfb_card_id != -1 && i != ivtvfb_card_id) put_driver(drv);
continue;
itv = ivtv_cards[i];
if (itv && (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) {
if (ivtvfb_init_card(itv) == 0) {
IVTVFB_INFO("Framebuffer registered on ivtv card id %d\n", i);
registered++;
}
}
}
if (!registered) { if (!registered) {
printk(KERN_ERR "ivtvfb: no cards found"); printk(KERN_ERR "ivtvfb: no cards found\n");
return -ENODEV; return -ENODEV;
} }
return 0; return 0;
...@@ -1220,24 +1247,14 @@ static int __init ivtvfb_init(void) ...@@ -1220,24 +1247,14 @@ static int __init ivtvfb_init(void)
static void ivtvfb_cleanup(void) static void ivtvfb_cleanup(void)
{ {
struct ivtv *itv; struct device_driver *drv;
int i; int err;
printk(KERN_INFO "ivtvfb: Unloading framebuffer module\n"); printk(KERN_INFO "ivtvfb: Unloading framebuffer module\n");
for (i = 0; i < ivtv_cards_active; i++) { drv = driver_find("ivtv", &pci_bus_type);
itv = ivtv_cards[i]; err = driver_for_each_device(drv, NULL, NULL, ivtvfb_callback_cleanup);
if (itv && (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) && itv->osd_info) { put_driver(drv);
if (unregister_framebuffer(&itv->osd_info->ivtvfb_info)) {
IVTVFB_WARN("Framebuffer %d is in use, cannot unload\n", i);
return;
}
IVTVFB_DEBUG_INFO("Unregister framebuffer %d\n", i);
ivtvfb_blank(FB_BLANK_POWERDOWN, &itv->osd_info->ivtvfb_info);
ivtvfb_release_buffers(itv);
itv->osd_video_pbase = 0;
}
}
} }
module_init(ivtvfb_init); module_init(ivtvfb_init);
......
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