diff options
author | Michael Krufky <mkrufky@linuxtv.org> | 2008-01-06 13:52:56 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@infradead.org> | 2008-01-25 16:04:43 -0500 |
commit | a4f263b587573f47cc6bc7ad85e5f650169d48f6 (patch) | |
tree | d6734ff3a2d7234b34086152fe08c6606973f5b2 /drivers | |
parent | b3d98135aa6e462d7e3f42a86d12483a9003a4da (diff) |
V4L/DVB (6986): tda18271: share state between analog and digital tuner instances
Signed-off-by: Michael Krufky <mkrufky@linuxtv.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/media/dvb/frontends/tda18271-fe.c | 93 | ||||
-rw-r--r-- | drivers/media/dvb/frontends/tda18271-priv.h | 3 | ||||
-rw-r--r-- | drivers/media/video/tda8290.c | 9 |
3 files changed, 81 insertions, 24 deletions
diff --git a/drivers/media/dvb/frontends/tda18271-fe.c b/drivers/media/dvb/frontends/tda18271-fe.c index e860f4c009c2..aa93e1550627 100644 --- a/drivers/media/dvb/frontends/tda18271-fe.c +++ b/drivers/media/dvb/frontends/tda18271-fe.c | |||
@@ -27,6 +27,9 @@ module_param_named(debug, tda18271_debug, int, 0644); | |||
27 | MODULE_PARM_DESC(debug, "set debug level " | 27 | MODULE_PARM_DESC(debug, "set debug level " |
28 | "(info=1, map=2, reg=4, adv=8 (or-able))"); | 28 | "(info=1, map=2, reg=4, adv=8 (or-able))"); |
29 | 29 | ||
30 | static LIST_HEAD(tda18271_list); | ||
31 | static DEFINE_MUTEX(tda18271_list_mutex); | ||
32 | |||
30 | /*---------------------------------------------------------------------*/ | 33 | /*---------------------------------------------------------------------*/ |
31 | 34 | ||
32 | static int tda18271_ir_cal_init(struct dvb_frontend *fe) | 35 | static int tda18271_ir_cal_init(struct dvb_frontend *fe) |
@@ -936,8 +939,24 @@ fail: | |||
936 | 939 | ||
937 | static int tda18271_release(struct dvb_frontend *fe) | 940 | static int tda18271_release(struct dvb_frontend *fe) |
938 | { | 941 | { |
939 | kfree(fe->tuner_priv); | 942 | struct tda18271_priv *priv = fe->tuner_priv; |
943 | |||
944 | mutex_lock(&tda18271_list_mutex); | ||
945 | |||
946 | priv->count--; | ||
947 | |||
948 | if (!priv->count) { | ||
949 | tda_dbg("destroying instance @ %d-%04x\n", | ||
950 | i2c_adapter_id(priv->i2c_adap), | ||
951 | priv->i2c_addr); | ||
952 | list_del(&priv->tda18271_list); | ||
953 | |||
954 | kfree(priv); | ||
955 | } | ||
956 | mutex_unlock(&tda18271_list_mutex); | ||
957 | |||
940 | fe->tuner_priv = NULL; | 958 | fe->tuner_priv = NULL; |
959 | |||
941 | return 0; | 960 | return 0; |
942 | } | 961 | } |
943 | 962 | ||
@@ -1071,43 +1090,73 @@ struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr, | |||
1071 | struct tda18271_config *cfg) | 1090 | struct tda18271_config *cfg) |
1072 | { | 1091 | { |
1073 | struct tda18271_priv *priv = NULL; | 1092 | struct tda18271_priv *priv = NULL; |
1093 | int state_found = 0; | ||
1094 | |||
1095 | mutex_lock(&tda18271_list_mutex); | ||
1096 | |||
1097 | list_for_each_entry(priv, &tda18271_list, tda18271_list) { | ||
1098 | if ((i2c_adapter_id(priv->i2c_adap) == i2c_adapter_id(i2c)) && | ||
1099 | (priv->i2c_addr == addr)) { | ||
1100 | tda_dbg("attaching existing tuner @ %d-%04x\n", | ||
1101 | i2c_adapter_id(priv->i2c_adap), | ||
1102 | priv->i2c_addr); | ||
1103 | priv->count++; | ||
1104 | fe->tuner_priv = priv; | ||
1105 | state_found = 1; | ||
1106 | /* allow dvb driver to override i2c gate setting */ | ||
1107 | if ((cfg) && (cfg->gate != TDA18271_GATE_ANALOG)) | ||
1108 | priv->gate = cfg->gate; | ||
1109 | break; | ||
1110 | } | ||
1111 | } | ||
1112 | if (state_found == 0) { | ||
1113 | tda_dbg("creating new tuner instance @ %d-%04x\n", | ||
1114 | i2c_adapter_id(i2c), addr); | ||
1115 | |||
1116 | priv = kzalloc(sizeof(struct tda18271_priv), GFP_KERNEL); | ||
1117 | if (priv == NULL) { | ||
1118 | mutex_unlock(&tda18271_list_mutex); | ||
1119 | return NULL; | ||
1120 | } | ||
1074 | 1121 | ||
1075 | priv = kzalloc(sizeof(struct tda18271_priv), GFP_KERNEL); | 1122 | priv->i2c_addr = addr; |
1076 | if (priv == NULL) | 1123 | priv->i2c_adap = i2c; |
1077 | return NULL; | 1124 | priv->gate = (cfg) ? cfg->gate : TDA18271_GATE_AUTO; |
1125 | priv->cal_initialized = false; | ||
1126 | mutex_init(&priv->lock); | ||
1127 | priv->count++; | ||
1078 | 1128 | ||
1079 | priv->i2c_addr = addr; | 1129 | fe->tuner_priv = priv; |
1080 | priv->i2c_adap = i2c; | ||
1081 | priv->gate = (cfg) ? cfg->gate : TDA18271_GATE_AUTO; | ||
1082 | priv->cal_initialized = false; | ||
1083 | mutex_init(&priv->lock); | ||
1084 | 1130 | ||
1085 | fe->tuner_priv = priv; | 1131 | list_add_tail(&priv->tda18271_list, &tda18271_list); |
1086 | 1132 | ||
1087 | if (tda18271_get_id(fe) < 0) | 1133 | if (tda18271_get_id(fe) < 0) |
1088 | goto fail; | 1134 | goto fail; |
1089 | 1135 | ||
1090 | if (tda18271_assign_map_layout(fe) < 0) | 1136 | if (tda18271_assign_map_layout(fe) < 0) |
1091 | goto fail; | 1137 | goto fail; |
1092 | 1138 | ||
1093 | memcpy(&fe->ops.tuner_ops, &tda18271_tuner_ops, | 1139 | mutex_lock(&priv->lock); |
1094 | sizeof(struct dvb_tuner_ops)); | 1140 | tda18271_init_regs(fe); |
1141 | mutex_unlock(&priv->lock); | ||
1142 | } | ||
1095 | 1143 | ||
1096 | /* override default std map with values in config struct */ | 1144 | /* override default std map with values in config struct */ |
1097 | if ((cfg) && (cfg->std_map)) | 1145 | if ((cfg) && (cfg->std_map)) |
1098 | tda18271_update_std_map(fe, cfg->std_map); | 1146 | tda18271_update_std_map(fe, cfg->std_map); |
1099 | 1147 | ||
1100 | if (tda18271_debug & DBG_MAP) | 1148 | mutex_unlock(&tda18271_list_mutex); |
1101 | tda18271_dump_std_map(fe); | ||
1102 | |||
1103 | mutex_lock(&priv->lock); | ||
1104 | 1149 | ||
1105 | tda18271_init_regs(fe); | 1150 | memcpy(&fe->ops.tuner_ops, &tda18271_tuner_ops, |
1151 | sizeof(struct dvb_tuner_ops)); | ||
1106 | 1152 | ||
1107 | mutex_unlock(&priv->lock); | 1153 | if (tda18271_debug & DBG_MAP) |
1154 | tda18271_dump_std_map(fe); | ||
1108 | 1155 | ||
1109 | return fe; | 1156 | return fe; |
1110 | fail: | 1157 | fail: |
1158 | mutex_unlock(&tda18271_list_mutex); | ||
1159 | |||
1111 | tda18271_release(fe); | 1160 | tda18271_release(fe); |
1112 | return NULL; | 1161 | return NULL; |
1113 | } | 1162 | } |
diff --git a/drivers/media/dvb/frontends/tda18271-priv.h b/drivers/media/dvb/frontends/tda18271-priv.h index af89cfab0066..5c04d63ae849 100644 --- a/drivers/media/dvb/frontends/tda18271-priv.h +++ b/drivers/media/dvb/frontends/tda18271-priv.h | |||
@@ -102,10 +102,13 @@ struct tda18271_priv { | |||
102 | struct i2c_adapter *i2c_adap; | 102 | struct i2c_adapter *i2c_adap; |
103 | unsigned char tda18271_regs[TDA18271_NUM_REGS]; | 103 | unsigned char tda18271_regs[TDA18271_NUM_REGS]; |
104 | 104 | ||
105 | struct list_head tda18271_list; | ||
106 | |||
105 | enum tda18271_mode mode; | 107 | enum tda18271_mode mode; |
106 | enum tda18271_i2c_gate gate; | 108 | enum tda18271_i2c_gate gate; |
107 | enum tda18271_ver id; | 109 | enum tda18271_ver id; |
108 | 110 | ||
111 | unsigned int count; | ||
109 | unsigned int tm_rfcal; | 112 | unsigned int tm_rfcal; |
110 | unsigned int cal_initialized:1; | 113 | unsigned int cal_initialized:1; |
111 | 114 | ||
diff --git a/drivers/media/video/tda8290.c b/drivers/media/video/tda8290.c index eab530708a49..4ac7c0438896 100644 --- a/drivers/media/video/tda8290.c +++ b/drivers/media/video/tda8290.c | |||
@@ -502,8 +502,13 @@ static void tda8290_init_tuner(struct dvb_frontend *fe) | |||
502 | 502 | ||
503 | static void tda829x_release(struct dvb_frontend *fe) | 503 | static void tda829x_release(struct dvb_frontend *fe) |
504 | { | 504 | { |
505 | if (fe->ops.tuner_ops.release) | 505 | struct tda8290_priv *priv = fe->analog_demod_priv; |
506 | fe->ops.tuner_ops.release(fe); | 506 | |
507 | /* dont try to release the tuner | ||
508 | * if we didn't attach it from this module */ | ||
509 | if ((priv->ver > TDA8290) && (priv->ver > TDA8295)) | ||
510 | if (fe->ops.tuner_ops.release) | ||
511 | fe->ops.tuner_ops.release(fe); | ||
507 | 512 | ||
508 | kfree(fe->analog_demod_priv); | 513 | kfree(fe->analog_demod_priv); |
509 | fe->analog_demod_priv = NULL; | 514 | fe->analog_demod_priv = NULL; |