1
+ // SPDX-License-Identifier: GPL-2.0
1
2
/*
2
3
* tw9910 Video Driver
3
4
*
5
+ * Copyright (C) 2017 Jacopo Mondi <jacopo+renesas@jmondi.org>
6
+ *
4
7
* Copyright (C) 2008 Renesas Solutions Corp.
5
8
* Kuninori Morimoto <morimoto.kuninori@renesas.com>
6
9
*
10
13
* Copyright 2006-7 Jonathan Corbet <corbet@lwn.net>
11
14
* Copyright (C) 2008 Magnus Damm
12
15
* Copyright (C) 2008, Guennadi Liakhovetski <kernel@pengutronix.de>
13
- *
14
- * This program is free software; you can redistribute it and/or modify
15
- * it under the terms of the GNU General Public License version 2 as
16
- * published by the Free Software Foundation.
17
16
*/
18
17
18
+ #include <linux/clk.h>
19
+ #include <linux/gpio/consumer.h>
19
20
#include <linux/init.h>
20
21
#include <linux/module.h>
21
22
#include <linux/i2c.h>
25
26
#include <linux/v4l2-mediabus.h>
26
27
#include <linux/videodev2.h>
27
28
28
- #include <media/soc_camera.h>
29
29
#include <media/i2c/tw9910.h>
30
- #include <media/v4l2-clk.h>
31
30
#include <media/v4l2-subdev.h>
32
31
33
32
#define GET_ID (val ) ((val & 0xF8) >> 3)
@@ -228,8 +227,10 @@ struct tw9910_scale_ctrl {
228
227
229
228
struct tw9910_priv {
230
229
struct v4l2_subdev subdev ;
231
- struct v4l2_clk * clk ;
230
+ struct clk * clk ;
232
231
struct tw9910_video_info * info ;
232
+ struct gpio_desc * pdn_gpio ;
233
+ struct gpio_desc * rstb_gpio ;
233
234
const struct tw9910_scale_ctrl * scale ;
234
235
v4l2_std_id norm ;
235
236
u32 revision ;
@@ -582,13 +583,66 @@ static int tw9910_s_register(struct v4l2_subdev *sd,
582
583
}
583
584
#endif
584
585
586
+ static int tw9910_power_on (struct tw9910_priv * priv )
587
+ {
588
+ struct i2c_client * client = v4l2_get_subdevdata (& priv -> subdev );
589
+ int ret ;
590
+
591
+ if (priv -> clk ) {
592
+ ret = clk_prepare_enable (priv -> clk );
593
+ if (ret )
594
+ return ret ;
595
+ }
596
+
597
+ if (priv -> pdn_gpio ) {
598
+ gpiod_set_value (priv -> pdn_gpio , 0 );
599
+ usleep_range (500 , 1000 );
600
+ }
601
+
602
+ /*
603
+ * FIXME: The reset signal is connected to a shared GPIO on some
604
+ * platforms (namely the SuperH Migo-R). Until a framework becomes
605
+ * available to handle this cleanly, request the GPIO temporarily
606
+ * to avoid conflicts.
607
+ */
608
+ priv -> rstb_gpio = gpiod_get_optional (& client -> dev , "rstb" ,
609
+ GPIOD_OUT_LOW );
610
+ if (IS_ERR (priv -> rstb_gpio )) {
611
+ dev_info (& client -> dev , "Unable to get GPIO \"rstb\"" );
612
+ return PTR_ERR (priv -> rstb_gpio );
613
+ }
614
+
615
+ if (priv -> rstb_gpio ) {
616
+ gpiod_set_value (priv -> rstb_gpio , 1 );
617
+ usleep_range (500 , 1000 );
618
+ gpiod_set_value (priv -> rstb_gpio , 0 );
619
+ usleep_range (500 , 1000 );
620
+
621
+ gpiod_put (priv -> rstb_gpio );
622
+ }
623
+
624
+ return 0 ;
625
+ }
626
+
627
+ static int tw9910_power_off (struct tw9910_priv * priv )
628
+ {
629
+ clk_disable_unprepare (priv -> clk );
630
+
631
+ if (priv -> pdn_gpio ) {
632
+ gpiod_set_value (priv -> pdn_gpio , 1 );
633
+ usleep_range (500 , 1000 );
634
+ }
635
+
636
+ return 0 ;
637
+ }
638
+
585
639
static int tw9910_s_power (struct v4l2_subdev * sd , int on )
586
640
{
587
641
struct i2c_client * client = v4l2_get_subdevdata (sd );
588
- struct soc_camera_subdev_desc * ssdd = soc_camera_i2c_to_desc (client );
589
642
struct tw9910_priv * priv = to_tw9910 (client );
590
643
591
- return soc_camera_set_power (& client -> dev , ssdd , priv -> clk , on );
644
+ return on ? tw9910_power_on (priv ) :
645
+ tw9910_power_off (priv );
592
646
}
593
647
594
648
static int tw9910_set_frame (struct v4l2_subdev * sd , u32 * width , u32 * height )
@@ -614,7 +668,7 @@ static int tw9910_set_frame(struct v4l2_subdev *sd, u32 *width, u32 *height)
614
668
* set bus width
615
669
*/
616
670
val = 0x00 ;
617
- if (SOCAM_DATAWIDTH_16 == priv -> info -> buswidth )
671
+ if (priv -> info -> buswidth == 16 )
618
672
val = LEN ;
619
673
620
674
ret = tw9910_mask_set (client , OPFORM , LEN , val );
@@ -799,8 +853,7 @@ static int tw9910_video_probe(struct i2c_client *client)
799
853
/*
800
854
* tw9910 only use 8 or 16 bit bus width
801
855
*/
802
- if (SOCAM_DATAWIDTH_16 != priv -> info -> buswidth &&
803
- SOCAM_DATAWIDTH_8 != priv -> info -> buswidth ) {
856
+ if (priv -> info -> buswidth != 16 && priv -> info -> buswidth != 8 ) {
804
857
dev_err (& client -> dev , "bus width error\n" );
805
858
return - ENODEV ;
806
859
}
@@ -856,45 +909,6 @@ static int tw9910_enum_mbus_code(struct v4l2_subdev *sd,
856
909
return 0 ;
857
910
}
858
911
859
- static int tw9910_g_mbus_config (struct v4l2_subdev * sd ,
860
- struct v4l2_mbus_config * cfg )
861
- {
862
- struct i2c_client * client = v4l2_get_subdevdata (sd );
863
- struct soc_camera_subdev_desc * ssdd = soc_camera_i2c_to_desc (client );
864
-
865
- cfg -> flags = V4L2_MBUS_PCLK_SAMPLE_RISING | V4L2_MBUS_MASTER |
866
- V4L2_MBUS_VSYNC_ACTIVE_HIGH | V4L2_MBUS_VSYNC_ACTIVE_LOW |
867
- V4L2_MBUS_HSYNC_ACTIVE_HIGH | V4L2_MBUS_HSYNC_ACTIVE_LOW |
868
- V4L2_MBUS_DATA_ACTIVE_HIGH ;
869
- cfg -> type = V4L2_MBUS_PARALLEL ;
870
- cfg -> flags = soc_camera_apply_board_flags (ssdd , cfg );
871
-
872
- return 0 ;
873
- }
874
-
875
- static int tw9910_s_mbus_config (struct v4l2_subdev * sd ,
876
- const struct v4l2_mbus_config * cfg )
877
- {
878
- struct i2c_client * client = v4l2_get_subdevdata (sd );
879
- struct soc_camera_subdev_desc * ssdd = soc_camera_i2c_to_desc (client );
880
- u8 val = VSSL_VVALID | HSSL_DVALID ;
881
- unsigned long flags = soc_camera_apply_board_flags (ssdd , cfg );
882
-
883
- /*
884
- * set OUTCTR1
885
- *
886
- * We use VVALID and DVALID signals to control VSYNC and HSYNC
887
- * outputs, in this mode their polarity is inverted.
888
- */
889
- if (flags & V4L2_MBUS_HSYNC_ACTIVE_LOW )
890
- val |= HSP_HI ;
891
-
892
- if (flags & V4L2_MBUS_VSYNC_ACTIVE_LOW )
893
- val |= VSP_HI ;
894
-
895
- return i2c_smbus_write_byte_data (client , OUTCTR1 , val );
896
- }
897
-
898
912
static int tw9910_g_tvnorms (struct v4l2_subdev * sd , v4l2_std_id * norm )
899
913
{
900
914
* norm = V4L2_STD_NTSC | V4L2_STD_PAL ;
@@ -905,8 +919,6 @@ static const struct v4l2_subdev_video_ops tw9910_subdev_video_ops = {
905
919
.s_std = tw9910_s_std ,
906
920
.g_std = tw9910_g_std ,
907
921
.s_stream = tw9910_s_stream ,
908
- .g_mbus_config = tw9910_g_mbus_config ,
909
- .s_mbus_config = tw9910_s_mbus_config ,
910
922
.g_tvnorms = tw9910_g_tvnorms ,
911
923
};
912
924
@@ -935,15 +947,14 @@ static int tw9910_probe(struct i2c_client *client,
935
947
struct tw9910_video_info * info ;
936
948
struct i2c_adapter * adapter =
937
949
to_i2c_adapter (client -> dev .parent );
938
- struct soc_camera_subdev_desc * ssdd = soc_camera_i2c_to_desc (client );
939
950
int ret ;
940
951
941
- if (!ssdd || ! ssdd -> drv_priv ) {
952
+ if (!client -> dev . platform_data ) {
942
953
dev_err (& client -> dev , "TW9910: missing platform data!\n" );
943
954
return - EINVAL ;
944
955
}
945
956
946
- info = ssdd -> drv_priv ;
957
+ info = client -> dev . platform_data ;
947
958
948
959
if (!i2c_check_functionality (adapter , I2C_FUNC_SMBUS_BYTE_DATA )) {
949
960
dev_err (& client -> dev ,
@@ -959,21 +970,50 @@ static int tw9910_probe(struct i2c_client *client,
959
970
960
971
v4l2_i2c_subdev_init (& priv -> subdev , client , & tw9910_subdev_ops );
961
972
962
- priv -> clk = v4l2_clk_get (& client -> dev , "mclk" );
963
- if (IS_ERR (priv -> clk ))
973
+ priv -> clk = clk_get (& client -> dev , "xti" );
974
+ if (PTR_ERR (priv -> clk ) == - ENOENT ) {
975
+ priv -> clk = NULL ;
976
+ } else if (IS_ERR (priv -> clk )) {
977
+ dev_err (& client -> dev , "Unable to get xti clock\n" );
964
978
return PTR_ERR (priv -> clk );
979
+ }
980
+
981
+ priv -> pdn_gpio = gpiod_get_optional (& client -> dev , "pdn" ,
982
+ GPIOD_OUT_HIGH );
983
+ if (IS_ERR (priv -> pdn_gpio )) {
984
+ dev_info (& client -> dev , "Unable to get GPIO \"pdn\"" );
985
+ ret = PTR_ERR (priv -> pdn_gpio );
986
+ goto error_clk_put ;
987
+ }
965
988
966
989
ret = tw9910_video_probe (client );
967
990
if (ret < 0 )
968
- v4l2_clk_put (priv -> clk );
991
+ goto error_gpio_put ;
992
+
993
+ ret = v4l2_async_register_subdev (& priv -> subdev );
994
+ if (ret )
995
+ goto error_gpio_put ;
996
+
997
+ return ret ;
998
+
999
+ error_gpio_put :
1000
+ if (priv -> pdn_gpio )
1001
+ gpiod_put (priv -> pdn_gpio );
1002
+ error_clk_put :
1003
+ clk_put (priv -> clk );
969
1004
970
1005
return ret ;
971
1006
}
972
1007
973
1008
static int tw9910_remove (struct i2c_client * client )
974
1009
{
975
1010
struct tw9910_priv * priv = to_tw9910 (client );
976
- v4l2_clk_put (priv -> clk );
1011
+
1012
+ if (priv -> pdn_gpio )
1013
+ gpiod_put (priv -> pdn_gpio );
1014
+ clk_put (priv -> clk );
1015
+ v4l2_device_unregister_subdev (& priv -> subdev );
1016
+
977
1017
return 0 ;
978
1018
}
979
1019
@@ -994,6 +1034,6 @@ static struct i2c_driver tw9910_i2c_driver = {
994
1034
995
1035
module_i2c_driver (tw9910_i2c_driver );
996
1036
997
- MODULE_DESCRIPTION ("SoC Camera driver for tw9910 " );
1037
+ MODULE_DESCRIPTION ("V4L2 driver for TW9910 video decoder " );
998
1038
MODULE_AUTHOR ("Kuninori Morimoto" );
999
1039
MODULE_LICENSE ("GPL v2" );
0 commit comments