Loading drivers/media/video/saa7185.c +119 −98 Original line number Diff line number Diff line Loading @@ -30,51 +30,61 @@ #include <asm/uaccess.h> #include <linux/i2c.h> #include <linux/i2c-id.h> #include <linux/videodev.h> #include <linux/video_encoder.h> #include <media/v4l2-common.h> #include <linux/videodev2.h> #include <media/v4l2-device.h> #include <media/v4l2-chip-ident.h> #include <media/v4l2-i2c-drv-legacy.h> MODULE_DESCRIPTION("Philips SAA7185 video encoder driver"); MODULE_AUTHOR("Dave Perks"); MODULE_LICENSE("GPL"); static int debug; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level (0-1)"); static unsigned short normal_i2c[] = { 0x88 >> 1, I2C_CLIENT_END }; I2C_CLIENT_INSMOD; /* ----------------------------------------------------------------------- */ struct saa7185 { struct v4l2_subdev sd; unsigned char reg[128]; v4l2_std_id norm; int bright; int contrast; int hue; int sat; }; static inline struct saa7185 *to_saa7185(struct v4l2_subdev *sd) { return container_of(sd, struct saa7185, sd); } /* ----------------------------------------------------------------------- */ static inline int saa7185_read(struct i2c_client *client) static inline int saa7185_read(struct v4l2_subdev *sd) { struct i2c_client *client = v4l2_get_subdevdata(sd); return i2c_smbus_read_byte(client); } static int saa7185_write(struct i2c_client *client, u8 reg, u8 value) static int saa7185_write(struct v4l2_subdev *sd, u8 reg, u8 value) { struct saa7185 *encoder = i2c_get_clientdata(client); struct i2c_client *client = v4l2_get_subdevdata(sd); struct saa7185 *encoder = to_saa7185(sd); v4l_dbg(1, debug, client, "%02x set to %02x\n", reg, value); v4l2_dbg(1, debug, sd, "%02x set to %02x\n", reg, value); encoder->reg[reg] = value; return i2c_smbus_write_byte_data(client, reg, value); } static int saa7185_write_block(struct i2c_client *client, static int saa7185_write_block(struct v4l2_subdev *sd, const u8 *data, unsigned int len) { struct i2c_client *client = v4l2_get_subdevdata(sd); struct saa7185 *encoder = to_saa7185(sd); int ret = -1; u8 reg; Loading @@ -82,7 +92,6 @@ static int saa7185_write_block(struct i2c_client *client, * the adapter understands raw I2C */ if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { /* do raw I2C, not smbus compatible */ struct saa7185 *encoder = i2c_get_clientdata(client); u8 block_data[32]; int block_len; Loading @@ -103,7 +112,7 @@ static int saa7185_write_block(struct i2c_client *client, /* do some slow I2C emulation kind of thing */ while (len >= 2) { reg = *data++; ret = saa7185_write(client, reg, *data++); ret = saa7185_write(sd, reg, *data++); if (ret < 0) break; len -= 2; Loading Loading @@ -212,43 +221,36 @@ static const unsigned char init_ntsc[] = { 0x66, 0x21, /* FSC3 */ }; static int saa7185_command(struct i2c_client *client, unsigned cmd, void *arg) static int saa7185_init(struct v4l2_subdev *sd, u32 val) { struct saa7185 *encoder = i2c_get_clientdata(client); struct saa7185 *encoder = to_saa7185(sd); switch (cmd) { case VIDIOC_INT_INIT: saa7185_write_block(client, init_common, sizeof(init_common)); saa7185_write_block(sd, init_common, sizeof(init_common)); if (encoder->norm & V4L2_STD_NTSC) saa7185_write_block(client, init_ntsc, sizeof(init_ntsc)); saa7185_write_block(sd, init_ntsc, sizeof(init_ntsc)); else saa7185_write_block(client, init_pal, sizeof(init_pal)); break; saa7185_write_block(sd, init_pal, sizeof(init_pal)); return 0; } case VIDIOC_INT_S_STD_OUTPUT: static int saa7185_s_std_output(struct v4l2_subdev *sd, v4l2_std_id std) { v4l2_std_id *iarg = arg; struct saa7185 *encoder = to_saa7185(sd); //saa7185_write_block(client, init_common, sizeof(init_common)); if (*iarg & V4L2_STD_NTSC) saa7185_write_block(client, init_ntsc, sizeof(init_ntsc)); else if (*iarg & V4L2_STD_PAL) saa7185_write_block(client, init_pal, sizeof(init_pal)); if (std & V4L2_STD_NTSC) saa7185_write_block(sd, init_ntsc, sizeof(init_ntsc)); else if (std & V4L2_STD_PAL) saa7185_write_block(sd, init_pal, sizeof(init_pal)); else return -EINVAL; encoder->norm = *iarg; break; encoder->norm = std; return 0; } case VIDIOC_INT_S_VIDEO_ROUTING: static int saa7185_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *route) { struct v4l2_routing *route = arg; struct saa7185 *encoder = to_saa7185(sd); /* RJ: route->input = 0: input is from SA7111 route->input = 1: input is from ZR36060 */ Loading @@ -256,57 +258,74 @@ static int saa7185_command(struct i2c_client *client, unsigned cmd, void *arg) switch (route->input) { case 0: /* turn off colorbar */ saa7185_write(client, 0x3a, 0x0f); saa7185_write(sd, 0x3a, 0x0f); /* Switch RTCE to 1 */ saa7185_write(client, 0x61, (encoder->reg[0x61] & 0xf7) | 0x08); saa7185_write(client, 0x6e, 0x01); saa7185_write(sd, 0x61, (encoder->reg[0x61] & 0xf7) | 0x08); saa7185_write(sd, 0x6e, 0x01); break; case 1: /* turn off colorbar */ saa7185_write(client, 0x3a, 0x0f); saa7185_write(sd, 0x3a, 0x0f); /* Switch RTCE to 0 */ saa7185_write(client, 0x61, (encoder->reg[0x61] & 0xf7) | 0x00); saa7185_write(sd, 0x61, (encoder->reg[0x61] & 0xf7) | 0x00); /* SW: a slight sync problem... */ saa7185_write(client, 0x6e, 0x00); saa7185_write(sd, 0x6e, 0x00); break; case 2: /* turn on colorbar */ saa7185_write(client, 0x3a, 0x8f); saa7185_write(sd, 0x3a, 0x8f); /* Switch RTCE to 0 */ saa7185_write(client, 0x61, (encoder->reg[0x61] & 0xf7) | 0x08); saa7185_write(sd, 0x61, (encoder->reg[0x61] & 0xf7) | 0x08); /* SW: a slight sync problem... */ saa7185_write(client, 0x6e, 0x01); saa7185_write(sd, 0x6e, 0x01); break; default: return -EINVAL; } break; return 0; } default: return -EINVAL; static int saa7185_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) { struct i2c_client *client = v4l2_get_subdevdata(sd); return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_SAA7185, 0); } return 0; static int saa7185_command(struct i2c_client *client, unsigned cmd, void *arg) { return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); } /* ----------------------------------------------------------------------- */ static unsigned short normal_i2c[] = { 0x88 >> 1, I2C_CLIENT_END }; static const struct v4l2_subdev_core_ops saa7185_core_ops = { .g_chip_ident = saa7185_g_chip_ident, .init = saa7185_init, }; I2C_CLIENT_INSMOD; static const struct v4l2_subdev_video_ops saa7185_video_ops = { .s_std_output = saa7185_s_std_output, .s_routing = saa7185_s_routing, }; static const struct v4l2_subdev_ops saa7185_ops = { .core = &saa7185_core_ops, .video = &saa7185_video_ops, }; /* ----------------------------------------------------------------------- */ static int saa7185_probe(struct i2c_client *client, const struct i2c_device_id *id) { int i; struct saa7185 *encoder; struct v4l2_subdev *sd; /* Check if the adapter supports the needed features */ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) Loading @@ -319,26 +338,28 @@ static int saa7185_probe(struct i2c_client *client, if (encoder == NULL) return -ENOMEM; encoder->norm = V4L2_STD_NTSC; i2c_set_clientdata(client, encoder); sd = &encoder->sd; v4l2_i2c_subdev_init(sd, client, &saa7185_ops); i = saa7185_write_block(client, init_common, sizeof(init_common)); i = saa7185_write_block(sd, init_common, sizeof(init_common)); if (i >= 0) i = saa7185_write_block(client, init_ntsc, sizeof(init_ntsc)); i = saa7185_write_block(sd, init_ntsc, sizeof(init_ntsc)); if (i < 0) v4l_dbg(1, debug, client, "init error %d\n", i); v4l2_dbg(1, debug, sd, "init error %d\n", i); else v4l_dbg(1, debug, client, "revision 0x%x\n", saa7185_read(client) >> 5); v4l2_dbg(1, debug, sd, "revision 0x%x\n", saa7185_read(sd) >> 5); return 0; } static int saa7185_remove(struct i2c_client *client) { struct saa7185 *encoder = i2c_get_clientdata(client); saa7185_write(client, 0x61, (encoder->reg[0x61]) | 0x40); /* SW: output off is active */ //saa7185_write(client, 0x3a, (encoder->reg[0x3a]) | 0x80); /* SW: color bar */ struct v4l2_subdev *sd = i2c_get_clientdata(client); struct saa7185 *encoder = to_saa7185(sd); v4l2_device_unregister_subdev(sd); /* SW: output off is active */ saa7185_write(sd, 0x61, (encoder->reg[0x61]) | 0x40); kfree(encoder); return 0; } Loading include/media/v4l2-chip-ident.h +3 −0 Original line number Diff line number Diff line Loading @@ -113,6 +113,9 @@ enum { V4L2_IDENT_SAA6752HS = 6752, V4L2_IDENT_SAA6752HS_AC3 = 6753, /* module saa7185: just ident 7185 */ V4L2_IDENT_SAA7185 = 7185, /* module wm8739: just ident 8739 */ V4L2_IDENT_WM8739 = 8739, Loading Loading
drivers/media/video/saa7185.c +119 −98 Original line number Diff line number Diff line Loading @@ -30,51 +30,61 @@ #include <asm/uaccess.h> #include <linux/i2c.h> #include <linux/i2c-id.h> #include <linux/videodev.h> #include <linux/video_encoder.h> #include <media/v4l2-common.h> #include <linux/videodev2.h> #include <media/v4l2-device.h> #include <media/v4l2-chip-ident.h> #include <media/v4l2-i2c-drv-legacy.h> MODULE_DESCRIPTION("Philips SAA7185 video encoder driver"); MODULE_AUTHOR("Dave Perks"); MODULE_LICENSE("GPL"); static int debug; module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level (0-1)"); static unsigned short normal_i2c[] = { 0x88 >> 1, I2C_CLIENT_END }; I2C_CLIENT_INSMOD; /* ----------------------------------------------------------------------- */ struct saa7185 { struct v4l2_subdev sd; unsigned char reg[128]; v4l2_std_id norm; int bright; int contrast; int hue; int sat; }; static inline struct saa7185 *to_saa7185(struct v4l2_subdev *sd) { return container_of(sd, struct saa7185, sd); } /* ----------------------------------------------------------------------- */ static inline int saa7185_read(struct i2c_client *client) static inline int saa7185_read(struct v4l2_subdev *sd) { struct i2c_client *client = v4l2_get_subdevdata(sd); return i2c_smbus_read_byte(client); } static int saa7185_write(struct i2c_client *client, u8 reg, u8 value) static int saa7185_write(struct v4l2_subdev *sd, u8 reg, u8 value) { struct saa7185 *encoder = i2c_get_clientdata(client); struct i2c_client *client = v4l2_get_subdevdata(sd); struct saa7185 *encoder = to_saa7185(sd); v4l_dbg(1, debug, client, "%02x set to %02x\n", reg, value); v4l2_dbg(1, debug, sd, "%02x set to %02x\n", reg, value); encoder->reg[reg] = value; return i2c_smbus_write_byte_data(client, reg, value); } static int saa7185_write_block(struct i2c_client *client, static int saa7185_write_block(struct v4l2_subdev *sd, const u8 *data, unsigned int len) { struct i2c_client *client = v4l2_get_subdevdata(sd); struct saa7185 *encoder = to_saa7185(sd); int ret = -1; u8 reg; Loading @@ -82,7 +92,6 @@ static int saa7185_write_block(struct i2c_client *client, * the adapter understands raw I2C */ if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { /* do raw I2C, not smbus compatible */ struct saa7185 *encoder = i2c_get_clientdata(client); u8 block_data[32]; int block_len; Loading @@ -103,7 +112,7 @@ static int saa7185_write_block(struct i2c_client *client, /* do some slow I2C emulation kind of thing */ while (len >= 2) { reg = *data++; ret = saa7185_write(client, reg, *data++); ret = saa7185_write(sd, reg, *data++); if (ret < 0) break; len -= 2; Loading Loading @@ -212,43 +221,36 @@ static const unsigned char init_ntsc[] = { 0x66, 0x21, /* FSC3 */ }; static int saa7185_command(struct i2c_client *client, unsigned cmd, void *arg) static int saa7185_init(struct v4l2_subdev *sd, u32 val) { struct saa7185 *encoder = i2c_get_clientdata(client); struct saa7185 *encoder = to_saa7185(sd); switch (cmd) { case VIDIOC_INT_INIT: saa7185_write_block(client, init_common, sizeof(init_common)); saa7185_write_block(sd, init_common, sizeof(init_common)); if (encoder->norm & V4L2_STD_NTSC) saa7185_write_block(client, init_ntsc, sizeof(init_ntsc)); saa7185_write_block(sd, init_ntsc, sizeof(init_ntsc)); else saa7185_write_block(client, init_pal, sizeof(init_pal)); break; saa7185_write_block(sd, init_pal, sizeof(init_pal)); return 0; } case VIDIOC_INT_S_STD_OUTPUT: static int saa7185_s_std_output(struct v4l2_subdev *sd, v4l2_std_id std) { v4l2_std_id *iarg = arg; struct saa7185 *encoder = to_saa7185(sd); //saa7185_write_block(client, init_common, sizeof(init_common)); if (*iarg & V4L2_STD_NTSC) saa7185_write_block(client, init_ntsc, sizeof(init_ntsc)); else if (*iarg & V4L2_STD_PAL) saa7185_write_block(client, init_pal, sizeof(init_pal)); if (std & V4L2_STD_NTSC) saa7185_write_block(sd, init_ntsc, sizeof(init_ntsc)); else if (std & V4L2_STD_PAL) saa7185_write_block(sd, init_pal, sizeof(init_pal)); else return -EINVAL; encoder->norm = *iarg; break; encoder->norm = std; return 0; } case VIDIOC_INT_S_VIDEO_ROUTING: static int saa7185_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *route) { struct v4l2_routing *route = arg; struct saa7185 *encoder = to_saa7185(sd); /* RJ: route->input = 0: input is from SA7111 route->input = 1: input is from ZR36060 */ Loading @@ -256,57 +258,74 @@ static int saa7185_command(struct i2c_client *client, unsigned cmd, void *arg) switch (route->input) { case 0: /* turn off colorbar */ saa7185_write(client, 0x3a, 0x0f); saa7185_write(sd, 0x3a, 0x0f); /* Switch RTCE to 1 */ saa7185_write(client, 0x61, (encoder->reg[0x61] & 0xf7) | 0x08); saa7185_write(client, 0x6e, 0x01); saa7185_write(sd, 0x61, (encoder->reg[0x61] & 0xf7) | 0x08); saa7185_write(sd, 0x6e, 0x01); break; case 1: /* turn off colorbar */ saa7185_write(client, 0x3a, 0x0f); saa7185_write(sd, 0x3a, 0x0f); /* Switch RTCE to 0 */ saa7185_write(client, 0x61, (encoder->reg[0x61] & 0xf7) | 0x00); saa7185_write(sd, 0x61, (encoder->reg[0x61] & 0xf7) | 0x00); /* SW: a slight sync problem... */ saa7185_write(client, 0x6e, 0x00); saa7185_write(sd, 0x6e, 0x00); break; case 2: /* turn on colorbar */ saa7185_write(client, 0x3a, 0x8f); saa7185_write(sd, 0x3a, 0x8f); /* Switch RTCE to 0 */ saa7185_write(client, 0x61, (encoder->reg[0x61] & 0xf7) | 0x08); saa7185_write(sd, 0x61, (encoder->reg[0x61] & 0xf7) | 0x08); /* SW: a slight sync problem... */ saa7185_write(client, 0x6e, 0x01); saa7185_write(sd, 0x6e, 0x01); break; default: return -EINVAL; } break; return 0; } default: return -EINVAL; static int saa7185_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) { struct i2c_client *client = v4l2_get_subdevdata(sd); return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_SAA7185, 0); } return 0; static int saa7185_command(struct i2c_client *client, unsigned cmd, void *arg) { return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg); } /* ----------------------------------------------------------------------- */ static unsigned short normal_i2c[] = { 0x88 >> 1, I2C_CLIENT_END }; static const struct v4l2_subdev_core_ops saa7185_core_ops = { .g_chip_ident = saa7185_g_chip_ident, .init = saa7185_init, }; I2C_CLIENT_INSMOD; static const struct v4l2_subdev_video_ops saa7185_video_ops = { .s_std_output = saa7185_s_std_output, .s_routing = saa7185_s_routing, }; static const struct v4l2_subdev_ops saa7185_ops = { .core = &saa7185_core_ops, .video = &saa7185_video_ops, }; /* ----------------------------------------------------------------------- */ static int saa7185_probe(struct i2c_client *client, const struct i2c_device_id *id) { int i; struct saa7185 *encoder; struct v4l2_subdev *sd; /* Check if the adapter supports the needed features */ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) Loading @@ -319,26 +338,28 @@ static int saa7185_probe(struct i2c_client *client, if (encoder == NULL) return -ENOMEM; encoder->norm = V4L2_STD_NTSC; i2c_set_clientdata(client, encoder); sd = &encoder->sd; v4l2_i2c_subdev_init(sd, client, &saa7185_ops); i = saa7185_write_block(client, init_common, sizeof(init_common)); i = saa7185_write_block(sd, init_common, sizeof(init_common)); if (i >= 0) i = saa7185_write_block(client, init_ntsc, sizeof(init_ntsc)); i = saa7185_write_block(sd, init_ntsc, sizeof(init_ntsc)); if (i < 0) v4l_dbg(1, debug, client, "init error %d\n", i); v4l2_dbg(1, debug, sd, "init error %d\n", i); else v4l_dbg(1, debug, client, "revision 0x%x\n", saa7185_read(client) >> 5); v4l2_dbg(1, debug, sd, "revision 0x%x\n", saa7185_read(sd) >> 5); return 0; } static int saa7185_remove(struct i2c_client *client) { struct saa7185 *encoder = i2c_get_clientdata(client); saa7185_write(client, 0x61, (encoder->reg[0x61]) | 0x40); /* SW: output off is active */ //saa7185_write(client, 0x3a, (encoder->reg[0x3a]) | 0x80); /* SW: color bar */ struct v4l2_subdev *sd = i2c_get_clientdata(client); struct saa7185 *encoder = to_saa7185(sd); v4l2_device_unregister_subdev(sd); /* SW: output off is active */ saa7185_write(sd, 0x61, (encoder->reg[0x61]) | 0x40); kfree(encoder); return 0; } Loading
include/media/v4l2-chip-ident.h +3 −0 Original line number Diff line number Diff line Loading @@ -113,6 +113,9 @@ enum { V4L2_IDENT_SAA6752HS = 6752, V4L2_IDENT_SAA6752HS_AC3 = 6753, /* module saa7185: just ident 7185 */ V4L2_IDENT_SAA7185 = 7185, /* module wm8739: just ident 8739 */ V4L2_IDENT_WM8739 = 8739, Loading