Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

media: add tuner standby op, use where needed

The v4l2_subdev core s_power op was used for two different things: power on/off
sensors or video decoders/encoders and to put a tuner in standby (and only the
tuner!). There is no 'tuner wakeup' op, that's done automatically when the tuner
is accessed.

The danger with calling (s_power, 0) to put a tuner into standby is that it is
usually broadcast for all subdevs. So a video receiver subdev that supports
s_power will also be powered off, and since there is no corresponding (s_power, 1)
they will never be powered on again.

In addition, this is specifically meant for tuners only since they draw the most
current.

This patch adds a new tuner op called 'standby' and replaces all calls to
(core, s_power, 0) by (tuner, standby). This prevents confusion between the two
uses of s_power. Note that there is no overlap: bridge drivers either just want
to put the tuner into standby, or they deal with powering on/off sensors. Never
both.

This also makes it easier to replace s_power for the remaining bridge drivers
with some PM code later.

Whether we want something cleaner for tuners in the future is a separate topic.
There is a lot of legacy code surrounding tuners, and I am very hesitant about
making changes there.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>

authored by

Hans Verkuil and committed by
Mauro Carvalho Chehab
3aab15af 3f97df91

+28 -66
+1 -1
drivers/media/pci/cx23885/cx23885-core.c
··· 983 983 cx23885_i2c_register(&dev->i2c_bus[1]); 984 984 cx23885_i2c_register(&dev->i2c_bus[2]); 985 985 cx23885_card_setup(dev); 986 - call_all(dev, core, s_power, 0); 986 + call_all(dev, tuner, standby); 987 987 cx23885_ir_init(dev); 988 988 989 989 if (dev->board == CX23885_BOARD_VIEWCAST_460E) {
+2 -2
drivers/media/pci/cx23885/cx23885-dvb.c
··· 2568 2568 fe1->dvb.frontend->ops.ts_bus_ctrl = cx23885_dvb_bus_ctrl; 2569 2569 #endif 2570 2570 2571 - /* Put the analog decoder in standby to keep it quiet */ 2572 - call_all(dev, core, s_power, 0); 2571 + /* Put the tuner in standby to keep it quiet */ 2572 + call_all(dev, tuner, standby); 2573 2573 2574 2574 if (fe0->dvb.frontend->ops.analog_ops.standby) 2575 2575 fe0->dvb.frontend->ops.analog_ops.standby(fe0->dvb.frontend);
+1 -1
drivers/media/pci/cx88/cx88-cards.c
··· 3592 3592 ctl.fname); 3593 3593 call_all(core, tuner, s_config, &xc2028_cfg); 3594 3594 } 3595 - call_all(core, core, s_power, 0); 3595 + call_all(core, tuner, standby); 3596 3596 } 3597 3597 3598 3598 /* ------------------------------------------------------------------ */
+2 -2
drivers/media/pci/cx88/cx88-dvb.c
··· 1631 1631 if (fe1) 1632 1632 fe1->dvb.frontend->ops.ts_bus_ctrl = cx88_dvb_bus_ctrl; 1633 1633 1634 - /* Put the analog decoder in standby to keep it quiet */ 1635 - call_all(core, core, s_power, 0); 1634 + /* Put the tuner in standby to keep it quiet */ 1635 + call_all(core, tuner, standby); 1636 1636 1637 1637 /* register everything */ 1638 1638 res = vb2_dvb_register_bus(&dev->frontends, THIS_MODULE, dev,
+1 -1
drivers/media/pci/saa7134/saa7134-video.c
··· 1200 1200 saa_andorb(SAA7134_OFMT_DATA_A, 0x1f, 0); 1201 1201 saa_andorb(SAA7134_OFMT_DATA_B, 0x1f, 0); 1202 1202 1203 - saa_call_all(dev, core, s_power, 0); 1203 + saa_call_all(dev, tuner, standby); 1204 1204 if (vdev->vfl_type == VFL_TYPE_RADIO) 1205 1205 saa_call_all(dev, core, ioctl, SAA6588_CMD_CLOSE, &cmd); 1206 1206 mutex_unlock(&dev->lock);
+3 -13
drivers/media/tuners/e4000.c
··· 293 293 return container_of(sd, struct e4000_dev, sd); 294 294 } 295 295 296 - static int e4000_s_power(struct v4l2_subdev *sd, int on) 296 + static int e4000_standby(struct v4l2_subdev *sd) 297 297 { 298 298 struct e4000_dev *dev = e4000_subdev_to_dev(sd); 299 - struct i2c_client *client = dev->client; 300 299 int ret; 301 300 302 - dev_dbg(&client->dev, "on=%d\n", on); 303 - 304 - if (on) 305 - ret = e4000_init(dev); 306 - else 307 - ret = e4000_sleep(dev); 301 + ret = e4000_sleep(dev); 308 302 if (ret) 309 303 return ret; 310 304 311 305 return e4000_set_params(dev); 312 306 } 313 - 314 - static const struct v4l2_subdev_core_ops e4000_subdev_core_ops = { 315 - .s_power = e4000_s_power, 316 - }; 317 307 318 308 static int e4000_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *v) 319 309 { ··· 372 382 } 373 383 374 384 static const struct v4l2_subdev_tuner_ops e4000_subdev_tuner_ops = { 385 + .standby = e4000_standby, 375 386 .g_tuner = e4000_g_tuner, 376 387 .s_tuner = e4000_s_tuner, 377 388 .g_frequency = e4000_g_frequency, ··· 381 390 }; 382 391 383 392 static const struct v4l2_subdev_ops e4000_subdev_ops = { 384 - .core = &e4000_subdev_core_ops, 385 393 .tuner = &e4000_subdev_tuner_ops, 386 394 }; 387 395
+3 -13
drivers/media/tuners/fc2580.c
··· 386 386 return container_of(sd, struct fc2580_dev, subdev); 387 387 } 388 388 389 - static int fc2580_s_power(struct v4l2_subdev *sd, int on) 389 + static int fc2580_standby(struct v4l2_subdev *sd) 390 390 { 391 391 struct fc2580_dev *dev = fc2580_subdev_to_dev(sd); 392 - struct i2c_client *client = dev->client; 393 392 int ret; 394 393 395 - dev_dbg(&client->dev, "on=%d\n", on); 396 - 397 - if (on) 398 - ret = fc2580_init(dev); 399 - else 400 - ret = fc2580_sleep(dev); 394 + ret = fc2580_sleep(dev); 401 395 if (ret) 402 396 return ret; 403 397 404 398 return fc2580_set_params(dev); 405 399 } 406 - 407 - static const struct v4l2_subdev_core_ops fc2580_subdev_core_ops = { 408 - .s_power = fc2580_s_power, 409 - }; 410 400 411 401 static int fc2580_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *v) 412 402 { ··· 465 475 } 466 476 467 477 static const struct v4l2_subdev_tuner_ops fc2580_subdev_tuner_ops = { 478 + .standby = fc2580_standby, 468 479 .g_tuner = fc2580_g_tuner, 469 480 .s_tuner = fc2580_s_tuner, 470 481 .g_frequency = fc2580_g_frequency, ··· 474 483 }; 475 484 476 485 static const struct v4l2_subdev_ops fc2580_subdev_ops = { 477 - .core = &fc2580_subdev_core_ops, 478 486 .tuner = &fc2580_subdev_tuner_ops, 479 487 }; 480 488
+3 -16
drivers/media/tuners/msi001.c
··· 291 291 return ret; 292 292 } 293 293 294 - static int msi001_s_power(struct v4l2_subdev *sd, int on) 294 + static int msi001_standby(struct v4l2_subdev *sd) 295 295 { 296 296 struct msi001_dev *dev = sd_to_msi001_dev(sd); 297 - struct spi_device *spi = dev->spi; 298 - int ret; 299 297 300 - dev_dbg(&spi->dev, "on=%d\n", on); 301 - 302 - if (on) 303 - ret = 0; 304 - else 305 - ret = msi001_wreg(dev, 0x000000); 306 - 307 - return ret; 298 + return msi001_wreg(dev, 0x000000); 308 299 } 309 - 310 - static const struct v4l2_subdev_core_ops msi001_core_ops = { 311 - .s_power = msi001_s_power, 312 - }; 313 300 314 301 static int msi001_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *v) 315 302 { ··· 373 386 } 374 387 375 388 static const struct v4l2_subdev_tuner_ops msi001_tuner_ops = { 389 + .standby = msi001_standby, 376 390 .g_tuner = msi001_g_tuner, 377 391 .s_tuner = msi001_s_tuner, 378 392 .g_frequency = msi001_g_frequency, ··· 382 394 }; 383 395 384 396 static const struct v4l2_subdev_ops msi001_ops = { 385 - .core = &msi001_core_ops, 386 397 .tuner = &msi001_tuner_ops, 387 398 }; 388 399
+2 -2
drivers/media/usb/au0828/au0828-video.c
··· 1091 1091 */ 1092 1092 ret = v4l_enable_media_source(vdev); 1093 1093 if (ret == 0) 1094 - v4l2_device_call_all(&dev->v4l2_dev, 0, core, 1095 - s_power, 0); 1094 + v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, 1095 + standby); 1096 1096 dev->std_set_in_tuner_core = 0; 1097 1097 1098 1098 /* When close the device, set the usb intf0 into alt0 to free
+1 -1
drivers/media/usb/cx231xx/cx231xx-video.c
··· 1941 1941 } 1942 1942 1943 1943 /* Save some power by putting tuner to sleep */ 1944 - call_all(dev, core, s_power, 0); 1944 + call_all(dev, tuner, standby); 1945 1945 1946 1946 /* do this before setting alternate! */ 1947 1947 if (dev->USE_ISO)
+2 -2
drivers/media/usb/em28xx/em28xx-video.c
··· 2257 2257 goto exit; 2258 2258 2259 2259 /* Save some power by putting tuner to sleep */ 2260 - v4l2_device_call_all(&v4l2->v4l2_dev, 0, core, s_power, 0); 2260 + v4l2_device_call_all(&v4l2->v4l2_dev, 0, tuner, standby); 2261 2261 2262 2262 /* do this before setting alternate! */ 2263 2263 em28xx_set_mode(dev, EM28XX_SUSPEND); ··· 2810 2810 video_device_node_name(&v4l2->vbi_dev)); 2811 2811 2812 2812 /* Save some power by putting tuner to sleep */ 2813 - v4l2_device_call_all(&v4l2->v4l2_dev, 0, core, s_power, 0); 2813 + v4l2_device_call_all(&v4l2->v4l2_dev, 0, tuner, standby); 2814 2814 2815 2815 /* initialize videobuf2 stuff */ 2816 2816 em28xx_vb2_setup(dev);
+3 -12
drivers/media/v4l2-core/tuner-core.c
··· 1099 1099 */ 1100 1100 1101 1101 /** 1102 - * tuner_s_power - controls the power state of the tuner 1102 + * tuner_standby - places the tuner in standby mode 1103 1103 * @sd: pointer to struct v4l2_subdev 1104 - * @on: a zero value puts the tuner to sleep, non-zero wakes it up 1105 1104 */ 1106 - static int tuner_s_power(struct v4l2_subdev *sd, int on) 1105 + static int tuner_standby(struct v4l2_subdev *sd) 1107 1106 { 1108 1107 struct tuner *t = to_tuner(sd); 1109 1108 struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops; 1110 - 1111 - if (on) { 1112 - if (t->standby && set_mode(t, t->mode) == 0) { 1113 - dprintk("Waking up tuner\n"); 1114 - set_freq(t, 0); 1115 - } 1116 - return 0; 1117 - } 1118 1109 1119 1110 dprintk("Putting tuner to sleep\n"); 1120 1111 t->standby = true; ··· 1319 1328 1320 1329 static const struct v4l2_subdev_core_ops tuner_core_ops = { 1321 1330 .log_status = tuner_log_status, 1322 - .s_power = tuner_s_power, 1323 1331 }; 1324 1332 1325 1333 static const struct v4l2_subdev_tuner_ops tuner_tuner_ops = { 1334 + .standby = tuner_standby, 1326 1335 .s_radio = tuner_s_radio, 1327 1336 .g_tuner = tuner_g_tuner, 1328 1337 .s_tuner = tuner_s_tuner,
+4
include/media/v4l2-subdev.h
··· 224 224 * struct v4l2_subdev_tuner_ops - Callbacks used when v4l device was opened 225 225 * in radio mode. 226 226 * 227 + * @standby: puts the tuner in standby mode. It will be woken up 228 + * automatically the next time it is used. 229 + * 227 230 * @s_radio: callback that switches the tuner to radio mode. 228 231 * drivers should explicitly call it when a tuner ops should 229 232 * operate on radio mode, before being able to handle it. ··· 271 268 * } 272 269 */ 273 270 struct v4l2_subdev_tuner_ops { 271 + int (*standby)(struct v4l2_subdev *sd); 274 272 int (*s_radio)(struct v4l2_subdev *sd); 275 273 int (*s_frequency)(struct v4l2_subdev *sd, const struct v4l2_frequency *freq); 276 274 int (*g_frequency)(struct v4l2_subdev *sd, struct v4l2_frequency *freq);