| .. | .. |
|---|
| 20 | 20 | #include <linux/module.h> |
|---|
| 21 | 21 | #include <linux/of_graph.h> |
|---|
| 22 | 22 | #include <linux/rk-camera-module.h> |
|---|
| 23 | +#include <linux/rk_hdmirx_class.h> |
|---|
| 23 | 24 | #include <linux/slab.h> |
|---|
| 24 | 25 | #include <linux/timer.h> |
|---|
| 25 | 26 | #include <linux/v4l2-dv-timings.h> |
|---|
| .. | .. |
|---|
| 471 | 472 | struct regmap *mipi_regmap; |
|---|
| 472 | 473 | struct regmap *edid_regmap; |
|---|
| 473 | 474 | u8 attr_hdmi_reg_bank; |
|---|
| 474 | | - struct class *hdmirx_class; |
|---|
| 475 | 475 | struct device *dev; |
|---|
| 476 | 476 | struct device *classdev; |
|---|
| 477 | 477 | struct v4l2_fwnode_bus_mipi_csi2 bus; |
|---|
| .. | .. |
|---|
| 3519 | 3519 | return 0; |
|---|
| 3520 | 3520 | } |
|---|
| 3521 | 3521 | |
|---|
| 3522 | +static void it6616_detect_hot_plug(struct v4l2_subdev *sd) |
|---|
| 3523 | +{ |
|---|
| 3524 | + struct it6616 *it6616 = to_it6616(sd); |
|---|
| 3525 | + |
|---|
| 3526 | + if (it6616->mipi_tx_video_stable && it6616_hdmi_is_5v_on(it6616)) |
|---|
| 3527 | + v4l2_ctrl_s_ctrl(it6616->detect_tx_5v_ctrl, 1); |
|---|
| 3528 | + else |
|---|
| 3529 | + v4l2_ctrl_s_ctrl(it6616->detect_tx_5v_ctrl, 0); |
|---|
| 3530 | +} |
|---|
| 3531 | + |
|---|
| 3522 | 3532 | static void it6616_work_i2c_poll(struct work_struct *work) |
|---|
| 3523 | 3533 | { |
|---|
| 3524 | 3534 | struct delayed_work *dwork = to_delayed_work(work); |
|---|
| .. | .. |
|---|
| 3526 | 3536 | struct it6616, work_i2c_poll); |
|---|
| 3527 | 3537 | bool handled; |
|---|
| 3528 | 3538 | |
|---|
| 3529 | | - it6616_s_ctrl_detect_tx_5v(&it6616->sd); |
|---|
| 3530 | 3539 | it6616_isr(&it6616->sd, 0, &handled); |
|---|
| 3540 | + it6616_detect_hot_plug(&it6616->sd); |
|---|
| 3531 | 3541 | schedule_delayed_work(&it6616->work_i2c_poll, |
|---|
| 3532 | 3542 | msecs_to_jiffies(POLL_INTERVAL_MS)); |
|---|
| 3533 | 3543 | } |
|---|
| .. | .. |
|---|
| 4212 | 4222 | static DEVICE_ATTR_RO(audio_present); |
|---|
| 4213 | 4223 | static DEVICE_ATTR_RO(audio_rate); |
|---|
| 4214 | 4224 | |
|---|
| 4225 | +static struct attribute *it6616_audio_attrs[] = { |
|---|
| 4226 | + &dev_attr_audio_rate.attr, |
|---|
| 4227 | + &dev_attr_audio_present.attr, |
|---|
| 4228 | + NULL |
|---|
| 4229 | +}; |
|---|
| 4230 | +ATTRIBUTE_GROUPS(it6616_audio); |
|---|
| 4231 | + |
|---|
| 4215 | 4232 | static int it6616_create_class_attr(struct it6616 *it6616) |
|---|
| 4216 | 4233 | { |
|---|
| 4217 | | - int ret = 0; |
|---|
| 4218 | | - |
|---|
| 4219 | | - it6616->hdmirx_class = class_create(THIS_MODULE, "hdmirx_it6616"); |
|---|
| 4220 | | - if (IS_ERR(it6616->hdmirx_class)) { |
|---|
| 4221 | | - ret = -ENOMEM; |
|---|
| 4222 | | - dev_err(it6616->dev, "failed to create hdmirx_it6616 class!\n"); |
|---|
| 4223 | | - return ret; |
|---|
| 4224 | | - } |
|---|
| 4225 | | - |
|---|
| 4226 | | - it6616->classdev = device_create(it6616->hdmirx_class, NULL, |
|---|
| 4227 | | - MKDEV(0, 0), NULL, "hdmirx_it6616"); |
|---|
| 4228 | | - if (IS_ERR(it6616->classdev)) { |
|---|
| 4229 | | - ret = PTR_ERR(it6616->classdev); |
|---|
| 4230 | | - dev_err(it6616->dev, "Failed to create device\n"); |
|---|
| 4231 | | - goto err1; |
|---|
| 4232 | | - } |
|---|
| 4233 | | - |
|---|
| 4234 | | - ret = device_create_file(it6616->classdev, |
|---|
| 4235 | | - &dev_attr_audio_present); |
|---|
| 4236 | | - if (ret) { |
|---|
| 4237 | | - dev_err(it6616->dev, "failed to create attr audio_present!\n"); |
|---|
| 4238 | | - goto err1; |
|---|
| 4239 | | - } |
|---|
| 4240 | | - |
|---|
| 4241 | | - ret = device_create_file(it6616->classdev, |
|---|
| 4242 | | - &dev_attr_audio_rate); |
|---|
| 4243 | | - if (ret) { |
|---|
| 4244 | | - dev_err(it6616->dev, |
|---|
| 4245 | | - "failed to create attr audio_rate!\n"); |
|---|
| 4246 | | - goto err; |
|---|
| 4247 | | - } |
|---|
| 4248 | | - |
|---|
| 4249 | | - return ret; |
|---|
| 4250 | | - |
|---|
| 4251 | | -err: |
|---|
| 4252 | | - device_remove_file(it6616->classdev, &dev_attr_audio_present); |
|---|
| 4253 | | -err1: |
|---|
| 4254 | | - class_destroy(it6616->hdmirx_class); |
|---|
| 4255 | | - return ret; |
|---|
| 4234 | + it6616->classdev = device_create_with_groups(rk_hdmirx_class(), |
|---|
| 4235 | + it6616->dev, MKDEV(0, 0), |
|---|
| 4236 | + it6616, |
|---|
| 4237 | + it6616_audio_groups, |
|---|
| 4238 | + "it6616"); |
|---|
| 4239 | + if (IS_ERR(it6616->classdev)) |
|---|
| 4240 | + return IS_ERR(it6616->classdev); |
|---|
| 4241 | + return 0; |
|---|
| 4256 | 4242 | } |
|---|
| 4257 | 4243 | |
|---|
| 4258 | 4244 | static void it6616_remove_class_attr(struct it6616 *it6616) |
|---|
| 4259 | 4245 | { |
|---|
| 4260 | 4246 | device_remove_file(it6616->classdev, &dev_attr_audio_rate); |
|---|
| 4261 | 4247 | device_remove_file(it6616->classdev, &dev_attr_audio_present); |
|---|
| 4262 | | - class_destroy(it6616->hdmirx_class); |
|---|
| 4263 | 4248 | } |
|---|
| 4264 | 4249 | |
|---|
| 4265 | 4250 | static int it6616_probe(struct i2c_client *client, |
|---|