Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * upd64031A - NEC Electronics Ghost Reduction for NTSC in Japan
0004  *
0005  * 2003 by T.Adachi <tadachi@tadachi-net.com>
0006  * 2003 by Takeru KOMORIYA <komoriya@paken.org>
0007  * 2006 by Hans Verkuil <hverkuil@xs4all.nl>
0008  */
0009 
0010 
0011 #include <linux/module.h>
0012 #include <linux/kernel.h>
0013 #include <linux/i2c.h>
0014 #include <linux/videodev2.h>
0015 #include <linux/slab.h>
0016 #include <media/v4l2-device.h>
0017 #include <media/i2c/upd64031a.h>
0018 
0019 /* --------------------- read registers functions define -------------------- */
0020 
0021 /* bit masks */
0022 #define GR_MODE_MASK              0xc0
0023 #define DIRECT_3DYCS_CONNECT_MASK 0xc0
0024 #define SYNC_CIRCUIT_MASK         0xa0
0025 
0026 /* -------------------------------------------------------------------------- */
0027 
0028 MODULE_DESCRIPTION("uPD64031A driver");
0029 MODULE_AUTHOR("T. Adachi, Takeru KOMORIYA, Hans Verkuil");
0030 MODULE_LICENSE("GPL");
0031 
0032 static int debug;
0033 module_param(debug, int, 0644);
0034 
0035 MODULE_PARM_DESC(debug, "Debug level (0-1)");
0036 
0037 
0038 enum {
0039     R00 = 0, R01, R02, R03, R04,
0040     R05, R06, R07, R08, R09,
0041     R0A, R0B, R0C, R0D, R0E, R0F,
0042     /* unused registers
0043      R10, R11, R12, R13, R14,
0044      R15, R16, R17,
0045      */
0046     TOT_REGS
0047 };
0048 
0049 struct upd64031a_state {
0050     struct v4l2_subdev sd;
0051     u8 regs[TOT_REGS];
0052     u8 gr_mode;
0053     u8 direct_3dycs_connect;
0054     u8 ext_comp_sync;
0055     u8 ext_vert_sync;
0056 };
0057 
0058 static inline struct upd64031a_state *to_state(struct v4l2_subdev *sd)
0059 {
0060     return container_of(sd, struct upd64031a_state, sd);
0061 }
0062 
0063 static u8 upd64031a_init[] = {
0064     0x00, 0xb8, 0x48, 0xd2, 0xe6,
0065     0x03, 0x10, 0x0b, 0xaf, 0x7f,
0066     0x00, 0x00, 0x1d, 0x5e, 0x00,
0067     0xd0
0068 };
0069 
0070 /* ------------------------------------------------------------------------ */
0071 
0072 static u8 upd64031a_read(struct v4l2_subdev *sd, u8 reg)
0073 {
0074     struct i2c_client *client = v4l2_get_subdevdata(sd);
0075     u8 buf[2];
0076 
0077     if (reg >= sizeof(buf))
0078         return 0xff;
0079     i2c_master_recv(client, buf, 2);
0080     return buf[reg];
0081 }
0082 
0083 /* ------------------------------------------------------------------------ */
0084 
0085 static void upd64031a_write(struct v4l2_subdev *sd, u8 reg, u8 val)
0086 {
0087     struct i2c_client *client = v4l2_get_subdevdata(sd);
0088     u8 buf[2];
0089 
0090     buf[0] = reg;
0091     buf[1] = val;
0092     v4l2_dbg(1, debug, sd, "write reg: %02X val: %02X\n", reg, val);
0093     if (i2c_master_send(client, buf, 2) != 2)
0094         v4l2_err(sd, "I/O error write 0x%02x/0x%02x\n", reg, val);
0095 }
0096 
0097 /* ------------------------------------------------------------------------ */
0098 
0099 /* The input changed due to new input or channel changed */
0100 static int upd64031a_s_frequency(struct v4l2_subdev *sd, const struct v4l2_frequency *freq)
0101 {
0102     struct upd64031a_state *state = to_state(sd);
0103     u8 reg = state->regs[R00];
0104 
0105     v4l2_dbg(1, debug, sd, "changed input or channel\n");
0106     upd64031a_write(sd, R00, reg | 0x10);
0107     upd64031a_write(sd, R00, reg & ~0x10);
0108     return 0;
0109 }
0110 
0111 /* ------------------------------------------------------------------------ */
0112 
0113 static int upd64031a_s_routing(struct v4l2_subdev *sd,
0114                    u32 input, u32 output, u32 config)
0115 {
0116     struct upd64031a_state *state = to_state(sd);
0117     u8 r00, r05, r08;
0118 
0119     state->gr_mode = (input & 3) << 6;
0120     state->direct_3dycs_connect = (input & 0xc) << 4;
0121     state->ext_comp_sync =
0122         (input & UPD64031A_COMPOSITE_EXTERNAL) << 1;
0123     state->ext_vert_sync =
0124         (input & UPD64031A_VERTICAL_EXTERNAL) << 2;
0125     r00 = (state->regs[R00] & ~GR_MODE_MASK) | state->gr_mode;
0126     r05 = (state->regs[R00] & ~SYNC_CIRCUIT_MASK) |
0127         state->ext_comp_sync | state->ext_vert_sync;
0128     r08 = (state->regs[R08] & ~DIRECT_3DYCS_CONNECT_MASK) |
0129         state->direct_3dycs_connect;
0130     upd64031a_write(sd, R00, r00);
0131     upd64031a_write(sd, R05, r05);
0132     upd64031a_write(sd, R08, r08);
0133     return upd64031a_s_frequency(sd, NULL);
0134 }
0135 
0136 static int upd64031a_log_status(struct v4l2_subdev *sd)
0137 {
0138     v4l2_info(sd, "Status: SA00=0x%02x SA01=0x%02x\n",
0139             upd64031a_read(sd, 0), upd64031a_read(sd, 1));
0140     return 0;
0141 }
0142 
0143 #ifdef CONFIG_VIDEO_ADV_DEBUG
0144 static int upd64031a_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
0145 {
0146     reg->val = upd64031a_read(sd, reg->reg & 0xff);
0147     reg->size = 1;
0148     return 0;
0149 }
0150 
0151 static int upd64031a_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg)
0152 {
0153     upd64031a_write(sd, reg->reg & 0xff, reg->val & 0xff);
0154     return 0;
0155 }
0156 #endif
0157 
0158 /* ----------------------------------------------------------------------- */
0159 
0160 static const struct v4l2_subdev_core_ops upd64031a_core_ops = {
0161     .log_status = upd64031a_log_status,
0162 #ifdef CONFIG_VIDEO_ADV_DEBUG
0163     .g_register = upd64031a_g_register,
0164     .s_register = upd64031a_s_register,
0165 #endif
0166 };
0167 
0168 static const struct v4l2_subdev_tuner_ops upd64031a_tuner_ops = {
0169     .s_frequency = upd64031a_s_frequency,
0170 };
0171 
0172 static const struct v4l2_subdev_video_ops upd64031a_video_ops = {
0173     .s_routing = upd64031a_s_routing,
0174 };
0175 
0176 static const struct v4l2_subdev_ops upd64031a_ops = {
0177     .core = &upd64031a_core_ops,
0178     .tuner = &upd64031a_tuner_ops,
0179     .video = &upd64031a_video_ops,
0180 };
0181 
0182 /* ------------------------------------------------------------------------ */
0183 
0184 /* i2c implementation */
0185 
0186 static int upd64031a_probe(struct i2c_client *client,
0187                const struct i2c_device_id *id)
0188 {
0189     struct upd64031a_state *state;
0190     struct v4l2_subdev *sd;
0191     int i;
0192 
0193     if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
0194         return -EIO;
0195 
0196     v4l_info(client, "chip found @ 0x%x (%s)\n",
0197             client->addr << 1, client->adapter->name);
0198 
0199     state = devm_kzalloc(&client->dev, sizeof(*state), GFP_KERNEL);
0200     if (state == NULL)
0201         return -ENOMEM;
0202     sd = &state->sd;
0203     v4l2_i2c_subdev_init(sd, client, &upd64031a_ops);
0204     memcpy(state->regs, upd64031a_init, sizeof(state->regs));
0205     state->gr_mode = UPD64031A_GR_ON << 6;
0206     state->direct_3dycs_connect = UPD64031A_3DYCS_COMPOSITE << 4;
0207     state->ext_comp_sync = state->ext_vert_sync = 0;
0208     for (i = 0; i < TOT_REGS; i++)
0209         upd64031a_write(sd, i, state->regs[i]);
0210     return 0;
0211 }
0212 
0213 static int upd64031a_remove(struct i2c_client *client)
0214 {
0215     struct v4l2_subdev *sd = i2c_get_clientdata(client);
0216 
0217     v4l2_device_unregister_subdev(sd);
0218     return 0;
0219 }
0220 
0221 /* ----------------------------------------------------------------------- */
0222 
0223 static const struct i2c_device_id upd64031a_id[] = {
0224     { "upd64031a", 0 },
0225     { }
0226 };
0227 MODULE_DEVICE_TABLE(i2c, upd64031a_id);
0228 
0229 static struct i2c_driver upd64031a_driver = {
0230     .driver = {
0231         .name   = "upd64031a",
0232     },
0233     .probe      = upd64031a_probe,
0234     .remove     = upd64031a_remove,
0235     .id_table   = upd64031a_id,
0236 };
0237 
0238 module_i2c_driver(upd64031a_driver);