diff options
author | Martin Bugge <marbugge@cisco.com> | 2013-12-05 10:14:45 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <m.chehab@samsung.com> | 2014-01-07 03:37:08 -0500 |
commit | b82e2793476e7fd031ba9e3b0cad357d1534d1d1 (patch) | |
tree | 5b36abaed2264c80a3fef4536a8c7449dcee566d | |
parent | 245b2b678c6fc65f0265c55f7a4fa0155ad6b235 (diff) |
[media] adv7842: i2c dummy clients registration
Clear i2c_clients ptr when unregistered.
Warn if configured i2c-addr is zero.
Signed-off-by: Martin Bugge <marbugge@cisco.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
-rw-r--r-- | drivers/media/i2c/adv7842.c | 83 |
1 files changed, 63 insertions, 20 deletions
diff --git a/drivers/media/i2c/adv7842.c b/drivers/media/i2c/adv7842.c index 2920e6b4536d..108e1b02d6c8 100644 --- a/drivers/media/i2c/adv7842.c +++ b/drivers/media/i2c/adv7842.c | |||
@@ -2805,8 +2805,9 @@ static const struct v4l2_ctrl_config adv7842_ctrl_free_run_color = { | |||
2805 | }; | 2805 | }; |
2806 | 2806 | ||
2807 | 2807 | ||
2808 | static void adv7842_unregister_clients(struct adv7842_state *state) | 2808 | static void adv7842_unregister_clients(struct v4l2_subdev *sd) |
2809 | { | 2809 | { |
2810 | struct adv7842_state *state = to_state(sd); | ||
2810 | if (state->i2c_avlink) | 2811 | if (state->i2c_avlink) |
2811 | i2c_unregister_device(state->i2c_avlink); | 2812 | i2c_unregister_device(state->i2c_avlink); |
2812 | if (state->i2c_cec) | 2813 | if (state->i2c_cec) |
@@ -2829,15 +2830,71 @@ static void adv7842_unregister_clients(struct adv7842_state *state) | |||
2829 | i2c_unregister_device(state->i2c_cp); | 2830 | i2c_unregister_device(state->i2c_cp); |
2830 | if (state->i2c_vdp) | 2831 | if (state->i2c_vdp) |
2831 | i2c_unregister_device(state->i2c_vdp); | 2832 | i2c_unregister_device(state->i2c_vdp); |
2833 | |||
2834 | state->i2c_avlink = NULL; | ||
2835 | state->i2c_cec = NULL; | ||
2836 | state->i2c_infoframe = NULL; | ||
2837 | state->i2c_sdp_io = NULL; | ||
2838 | state->i2c_sdp = NULL; | ||
2839 | state->i2c_afe = NULL; | ||
2840 | state->i2c_repeater = NULL; | ||
2841 | state->i2c_edid = NULL; | ||
2842 | state->i2c_hdmi = NULL; | ||
2843 | state->i2c_cp = NULL; | ||
2844 | state->i2c_vdp = NULL; | ||
2832 | } | 2845 | } |
2833 | 2846 | ||
2834 | static struct i2c_client *adv7842_dummy_client(struct v4l2_subdev *sd, | 2847 | static struct i2c_client *adv7842_dummy_client(struct v4l2_subdev *sd, const char *desc, |
2835 | u8 addr, u8 io_reg) | 2848 | u8 addr, u8 io_reg) |
2836 | { | 2849 | { |
2837 | struct i2c_client *client = v4l2_get_subdevdata(sd); | 2850 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
2851 | struct i2c_client *cp; | ||
2838 | 2852 | ||
2839 | io_write(sd, io_reg, addr << 1); | 2853 | io_write(sd, io_reg, addr << 1); |
2840 | return i2c_new_dummy(client->adapter, io_read(sd, io_reg) >> 1); | 2854 | |
2855 | if (addr == 0) { | ||
2856 | v4l2_err(sd, "no %s i2c addr configured\n", desc); | ||
2857 | return NULL; | ||
2858 | } | ||
2859 | |||
2860 | cp = i2c_new_dummy(client->adapter, io_read(sd, io_reg) >> 1); | ||
2861 | if (!cp) | ||
2862 | v4l2_err(sd, "register %s on i2c addr 0x%x failed\n", desc, addr); | ||
2863 | |||
2864 | return cp; | ||
2865 | } | ||
2866 | |||
2867 | static int adv7842_register_clients(struct v4l2_subdev *sd) | ||
2868 | { | ||
2869 | struct adv7842_state *state = to_state(sd); | ||
2870 | struct adv7842_platform_data *pdata = &state->pdata; | ||
2871 | |||
2872 | state->i2c_avlink = adv7842_dummy_client(sd, "avlink", pdata->i2c_avlink, 0xf3); | ||
2873 | state->i2c_cec = adv7842_dummy_client(sd, "cec", pdata->i2c_cec, 0xf4); | ||
2874 | state->i2c_infoframe = adv7842_dummy_client(sd, "infoframe", pdata->i2c_infoframe, 0xf5); | ||
2875 | state->i2c_sdp_io = adv7842_dummy_client(sd, "sdp_io", pdata->i2c_sdp_io, 0xf2); | ||
2876 | state->i2c_sdp = adv7842_dummy_client(sd, "sdp", pdata->i2c_sdp, 0xf1); | ||
2877 | state->i2c_afe = adv7842_dummy_client(sd, "afe", pdata->i2c_afe, 0xf8); | ||
2878 | state->i2c_repeater = adv7842_dummy_client(sd, "repeater", pdata->i2c_repeater, 0xf9); | ||
2879 | state->i2c_edid = adv7842_dummy_client(sd, "edid", pdata->i2c_edid, 0xfa); | ||
2880 | state->i2c_hdmi = adv7842_dummy_client(sd, "hdmi", pdata->i2c_hdmi, 0xfb); | ||
2881 | state->i2c_cp = adv7842_dummy_client(sd, "cp", pdata->i2c_cp, 0xfd); | ||
2882 | state->i2c_vdp = adv7842_dummy_client(sd, "vdp", pdata->i2c_vdp, 0xfe); | ||
2883 | |||
2884 | if (!state->i2c_avlink || | ||
2885 | !state->i2c_cec || | ||
2886 | !state->i2c_infoframe || | ||
2887 | !state->i2c_sdp_io || | ||
2888 | !state->i2c_sdp || | ||
2889 | !state->i2c_afe || | ||
2890 | !state->i2c_repeater || | ||
2891 | !state->i2c_edid || | ||
2892 | !state->i2c_hdmi || | ||
2893 | !state->i2c_cp || | ||
2894 | !state->i2c_vdp) | ||
2895 | return -1; | ||
2896 | |||
2897 | return 0; | ||
2841 | } | 2898 | } |
2842 | 2899 | ||
2843 | static int adv7842_probe(struct i2c_client *client, | 2900 | static int adv7842_probe(struct i2c_client *client, |
@@ -2939,21 +2996,7 @@ static int adv7842_probe(struct i2c_client *client, | |||
2939 | goto err_hdl; | 2996 | goto err_hdl; |
2940 | } | 2997 | } |
2941 | 2998 | ||
2942 | state->i2c_avlink = adv7842_dummy_client(sd, pdata->i2c_avlink, 0xf3); | 2999 | if (adv7842_register_clients(sd) < 0) { |
2943 | state->i2c_cec = adv7842_dummy_client(sd, pdata->i2c_cec, 0xf4); | ||
2944 | state->i2c_infoframe = adv7842_dummy_client(sd, pdata->i2c_infoframe, 0xf5); | ||
2945 | state->i2c_sdp_io = adv7842_dummy_client(sd, pdata->i2c_sdp_io, 0xf2); | ||
2946 | state->i2c_sdp = adv7842_dummy_client(sd, pdata->i2c_sdp, 0xf1); | ||
2947 | state->i2c_afe = adv7842_dummy_client(sd, pdata->i2c_afe, 0xf8); | ||
2948 | state->i2c_repeater = adv7842_dummy_client(sd, pdata->i2c_repeater, 0xf9); | ||
2949 | state->i2c_edid = adv7842_dummy_client(sd, pdata->i2c_edid, 0xfa); | ||
2950 | state->i2c_hdmi = adv7842_dummy_client(sd, pdata->i2c_hdmi, 0xfb); | ||
2951 | state->i2c_cp = adv7842_dummy_client(sd, pdata->i2c_cp, 0xfd); | ||
2952 | state->i2c_vdp = adv7842_dummy_client(sd, pdata->i2c_vdp, 0xfe); | ||
2953 | if (!state->i2c_avlink || !state->i2c_cec || !state->i2c_infoframe || | ||
2954 | !state->i2c_sdp_io || !state->i2c_sdp || !state->i2c_afe || | ||
2955 | !state->i2c_repeater || !state->i2c_edid || !state->i2c_hdmi || | ||
2956 | !state->i2c_cp || !state->i2c_vdp) { | ||
2957 | err = -ENOMEM; | 3000 | err = -ENOMEM; |
2958 | v4l2_err(sd, "failed to create all i2c clients\n"); | 3001 | v4l2_err(sd, "failed to create all i2c clients\n"); |
2959 | goto err_i2c; | 3002 | goto err_i2c; |
@@ -2989,7 +3032,7 @@ err_work_queues: | |||
2989 | cancel_delayed_work(&state->delayed_work_enable_hotplug); | 3032 | cancel_delayed_work(&state->delayed_work_enable_hotplug); |
2990 | destroy_workqueue(state->work_queues); | 3033 | destroy_workqueue(state->work_queues); |
2991 | err_i2c: | 3034 | err_i2c: |
2992 | adv7842_unregister_clients(state); | 3035 | adv7842_unregister_clients(sd); |
2993 | err_hdl: | 3036 | err_hdl: |
2994 | v4l2_ctrl_handler_free(hdl); | 3037 | v4l2_ctrl_handler_free(hdl); |
2995 | return err; | 3038 | return err; |
@@ -3008,7 +3051,7 @@ static int adv7842_remove(struct i2c_client *client) | |||
3008 | destroy_workqueue(state->work_queues); | 3051 | destroy_workqueue(state->work_queues); |
3009 | v4l2_device_unregister_subdev(sd); | 3052 | v4l2_device_unregister_subdev(sd); |
3010 | media_entity_cleanup(&sd->entity); | 3053 | media_entity_cleanup(&sd->entity); |
3011 | adv7842_unregister_clients(to_state(sd)); | 3054 | adv7842_unregister_clients(sd); |
3012 | v4l2_ctrl_handler_free(sd->ctrl_handler); | 3055 | v4l2_ctrl_handler_free(sd->ctrl_handler); |
3013 | return 0; | 3056 | return 0; |
3014 | } | 3057 | } |