Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright (C) 2005-2006 Micronas USA Inc.
0004  */
0005 
0006 #include <linux/module.h>
0007 #include <linux/init.h>
0008 #include <linux/i2c.h>
0009 #include <linux/videodev2.h>
0010 #include <linux/ioctl.h>
0011 #include <media/v4l2-device.h>
0012 #include <media/v4l2-ctrls.h>
0013 #include <linux/slab.h>
0014 
0015 MODULE_DESCRIPTION("TW9903 I2C subdev driver");
0016 MODULE_LICENSE("GPL v2");
0017 
0018 /*
0019  * This driver is based on the wis-tw9903.c source that was in
0020  * drivers/staging/media/go7007. That source had commented out code for
0021  * saturation and scaling (neither seemed to work). If anyone ever gets
0022  * hardware to test this driver, then that code might be useful to look at.
0023  * You need to get the kernel sources of, say, kernel 3.8 where that
0024  * wis-tw9903 driver is still present.
0025  */
0026 
0027 struct tw9903 {
0028     struct v4l2_subdev sd;
0029     struct v4l2_ctrl_handler hdl;
0030     v4l2_std_id norm;
0031 };
0032 
0033 static inline struct tw9903 *to_state(struct v4l2_subdev *sd)
0034 {
0035     return container_of(sd, struct tw9903, sd);
0036 }
0037 
0038 static const u8 initial_registers[] = {
0039     0x02, 0x44, /* input 1, composite */
0040     0x03, 0x92, /* correct digital format */
0041     0x04, 0x00,
0042     0x05, 0x80, /* or 0x00 for PAL */
0043     0x06, 0x40, /* second internal current reference */
0044     0x07, 0x02, /* window */
0045     0x08, 0x14, /* window */
0046     0x09, 0xf0, /* window */
0047     0x0a, 0x81, /* window */
0048     0x0b, 0xd0, /* window */
0049     0x0c, 0x8c,
0050     0x0d, 0x00, /* scaling */
0051     0x0e, 0x11, /* scaling */
0052     0x0f, 0x00, /* scaling */
0053     0x10, 0x00, /* brightness */
0054     0x11, 0x60, /* contrast */
0055     0x12, 0x01, /* sharpness */
0056     0x13, 0x7f, /* U gain */
0057     0x14, 0x5a, /* V gain */
0058     0x15, 0x00, /* hue */
0059     0x16, 0xc3, /* sharpness */
0060     0x18, 0x00,
0061     0x19, 0x58, /* vbi */
0062     0x1a, 0x80,
0063     0x1c, 0x0f, /* video norm */
0064     0x1d, 0x7f, /* video norm */
0065     0x20, 0xa0, /* clamping gain (working 0x50) */
0066     0x21, 0x22,
0067     0x22, 0xf0,
0068     0x23, 0xfe,
0069     0x24, 0x3c,
0070     0x25, 0x38,
0071     0x26, 0x44,
0072     0x27, 0x20,
0073     0x28, 0x00,
0074     0x29, 0x15,
0075     0x2a, 0xa0,
0076     0x2b, 0x44,
0077     0x2c, 0x37,
0078     0x2d, 0x00,
0079     0x2e, 0xa5, /* burst PLL control (working: a9) */
0080     0x2f, 0xe0, /* 0xea is blue test frame -- 0xe0 for normal */
0081     0x31, 0x00,
0082     0x33, 0x22,
0083     0x34, 0x11,
0084     0x35, 0x35,
0085     0x3b, 0x05,
0086     0x06, 0xc0, /* reset device */
0087     0x00, 0x00, /* Terminator (reg 0x00 is read-only) */
0088 };
0089 
0090 static int write_reg(struct v4l2_subdev *sd, u8 reg, u8 value)
0091 {
0092     struct i2c_client *client = v4l2_get_subdevdata(sd);
0093 
0094     return i2c_smbus_write_byte_data(client, reg, value);
0095 }
0096 
0097 static int write_regs(struct v4l2_subdev *sd, const u8 *regs)
0098 {
0099     int i;
0100 
0101     for (i = 0; regs[i] != 0x00; i += 2)
0102         if (write_reg(sd, regs[i], regs[i + 1]) < 0)
0103             return -1;
0104     return 0;
0105 }
0106 
0107 static int tw9903_s_video_routing(struct v4l2_subdev *sd, u32 input,
0108                       u32 output, u32 config)
0109 {
0110     write_reg(sd, 0x02, 0x40 | (input << 1));
0111     return 0;
0112 }
0113 
0114 static int tw9903_s_std(struct v4l2_subdev *sd, v4l2_std_id norm)
0115 {
0116     struct tw9903 *dec = to_state(sd);
0117     bool is_60hz = norm & V4L2_STD_525_60;
0118     static const u8 config_60hz[] = {
0119         0x05, 0x80,
0120         0x07, 0x02,
0121         0x08, 0x14,
0122         0x09, 0xf0,
0123         0,    0,
0124     };
0125     static const u8 config_50hz[] = {
0126         0x05, 0x00,
0127         0x07, 0x12,
0128         0x08, 0x18,
0129         0x09, 0x20,
0130         0,    0,
0131     };
0132 
0133     write_regs(sd, is_60hz ? config_60hz : config_50hz);
0134     dec->norm = norm;
0135     return 0;
0136 }
0137 
0138 
0139 static int tw9903_s_ctrl(struct v4l2_ctrl *ctrl)
0140 {
0141     struct tw9903 *dec = container_of(ctrl->handler, struct tw9903, hdl);
0142     struct v4l2_subdev *sd = &dec->sd;
0143 
0144     switch (ctrl->id) {
0145     case V4L2_CID_BRIGHTNESS:
0146         write_reg(sd, 0x10, ctrl->val);
0147         break;
0148     case V4L2_CID_CONTRAST:
0149         write_reg(sd, 0x11, ctrl->val);
0150         break;
0151     case V4L2_CID_HUE:
0152         write_reg(sd, 0x15, ctrl->val);
0153         break;
0154     default:
0155         return -EINVAL;
0156     }
0157     return 0;
0158 }
0159 
0160 static int tw9903_log_status(struct v4l2_subdev *sd)
0161 {
0162     struct tw9903 *dec = to_state(sd);
0163     bool is_60hz = dec->norm & V4L2_STD_525_60;
0164 
0165     v4l2_info(sd, "Standard: %d Hz\n", is_60hz ? 60 : 50);
0166     v4l2_ctrl_subdev_log_status(sd);
0167     return 0;
0168 }
0169 
0170 /* --------------------------------------------------------------------------*/
0171 
0172 static const struct v4l2_ctrl_ops tw9903_ctrl_ops = {
0173     .s_ctrl = tw9903_s_ctrl,
0174 };
0175 
0176 static const struct v4l2_subdev_core_ops tw9903_core_ops = {
0177     .log_status = tw9903_log_status,
0178 };
0179 
0180 static const struct v4l2_subdev_video_ops tw9903_video_ops = {
0181     .s_std = tw9903_s_std,
0182     .s_routing = tw9903_s_video_routing,
0183 };
0184 
0185 static const struct v4l2_subdev_ops tw9903_ops = {
0186     .core = &tw9903_core_ops,
0187     .video = &tw9903_video_ops,
0188 };
0189 
0190 /* --------------------------------------------------------------------------*/
0191 
0192 static int tw9903_probe(struct i2c_client *client,
0193                  const struct i2c_device_id *id)
0194 {
0195     struct tw9903 *dec;
0196     struct v4l2_subdev *sd;
0197     struct v4l2_ctrl_handler *hdl;
0198 
0199     /* Check if the adapter supports the needed features */
0200     if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
0201         return -EIO;
0202 
0203     v4l_info(client, "chip found @ 0x%02x (%s)\n",
0204             client->addr << 1, client->adapter->name);
0205 
0206     dec = devm_kzalloc(&client->dev, sizeof(*dec), GFP_KERNEL);
0207     if (dec == NULL)
0208         return -ENOMEM;
0209     sd = &dec->sd;
0210     v4l2_i2c_subdev_init(sd, client, &tw9903_ops);
0211     hdl = &dec->hdl;
0212     v4l2_ctrl_handler_init(hdl, 4);
0213     v4l2_ctrl_new_std(hdl, &tw9903_ctrl_ops,
0214         V4L2_CID_BRIGHTNESS, -128, 127, 1, 0);
0215     v4l2_ctrl_new_std(hdl, &tw9903_ctrl_ops,
0216         V4L2_CID_CONTRAST, 0, 255, 1, 0x60);
0217     v4l2_ctrl_new_std(hdl, &tw9903_ctrl_ops,
0218         V4L2_CID_HUE, -128, 127, 1, 0);
0219     sd->ctrl_handler = hdl;
0220     if (hdl->error) {
0221         int err = hdl->error;
0222 
0223         v4l2_ctrl_handler_free(hdl);
0224         return err;
0225     }
0226 
0227     /* Initialize tw9903 */
0228     dec->norm = V4L2_STD_NTSC;
0229 
0230     if (write_regs(sd, initial_registers) < 0) {
0231         v4l2_err(client, "error initializing TW9903\n");
0232         return -EINVAL;
0233     }
0234 
0235     return 0;
0236 }
0237 
0238 static int tw9903_remove(struct i2c_client *client)
0239 {
0240     struct v4l2_subdev *sd = i2c_get_clientdata(client);
0241 
0242     v4l2_device_unregister_subdev(sd);
0243     v4l2_ctrl_handler_free(&to_state(sd)->hdl);
0244     return 0;
0245 }
0246 
0247 /* ----------------------------------------------------------------------- */
0248 
0249 static const struct i2c_device_id tw9903_id[] = {
0250     { "tw9903", 0 },
0251     { }
0252 };
0253 MODULE_DEVICE_TABLE(i2c, tw9903_id);
0254 
0255 static struct i2c_driver tw9903_driver = {
0256     .driver = {
0257         .name   = "tw9903",
0258     },
0259     .probe = tw9903_probe,
0260     .remove = tw9903_remove,
0261     .id_table = tw9903_id,
0262 };
0263 module_i2c_driver(tw9903_driver);