static int si4713_set_rds_ps_name(struct si4713_device *sdev, char *ps_name) { int rval = 0, i; u8 len = 0; /* We want to clear the whole thing */ if (!strlen(ps_name)) memset(ps_name, 0, MAX_RDS_PS_NAME + 1); mutex_lock(&sdev->mutex); if (sdev->power_state) { /* Write the new ps name and clear the padding */ for (i = 0; i < MAX_RDS_PS_NAME; i += (RDS_BLOCK / 2)) { rval = si4713_tx_rds_ps(sdev, (i / (RDS_BLOCK / 2)), ps_name + i); if (rval < 0) goto unlock; } /* Setup the size to be sent */ if (strlen(ps_name)) len = strlen(ps_name) - 1; else len = 1; rval = si4713_write_property(sdev, SI4713_TX_RDS_PS_MESSAGE_COUNT, rds_ps_nblocks(len)); if (rval < 0) goto unlock; rval = si4713_write_property(sdev, SI4713_TX_RDS_PS_REPEAT_COUNT, DEFAULT_RDS_PS_REPEAT_COUNT * 2); if (rval < 0) goto unlock; } strncpy(sdev->rds_info.ps_name, ps_name, MAX_RDS_PS_NAME); unlock: mutex_unlock(&sdev->mutex); return rval; }
static int si4713_set_mute(struct si4713_device *sdev, u16 mute) { int rval = 0; mute = set_mute(mute); if (sdev->power_state) rval = si4713_write_property(sdev, SI4713_TX_LINE_INPUT_MUTE, mute); return rval; }
/* * si4713_powerup - Powers the device up * @sdev: si4713_device structure for the device we are communicating */ static int si4713_powerup(struct si4713_device *sdev) { int err; u8 resp[SI4713_PWUP_NRESP]; /* * .First byte = Enabled interrupts and boot function * .Second byte = Input operation mode */ const u8 args[SI4713_PWUP_NARGS] = { SI4713_PWUP_CTSIEN | SI4713_PWUP_GPO2OEN | SI4713_PWUP_FUNC_TX, SI4713_PWUP_OPMOD_ANALOG, }; if (sdev->power_state) return 0; err = regulator_bulk_enable(ARRAY_SIZE(sdev->supplies), sdev->supplies); if (err) { v4l2_err(&sdev->sd, "Failed to enable supplies: %d\n", err); return err; } if (gpio_is_valid(sdev->gpio_reset)) { udelay(50); gpio_set_value(sdev->gpio_reset, 1); } err = si4713_send_command(sdev, SI4713_CMD_POWER_UP, args, ARRAY_SIZE(args), resp, ARRAY_SIZE(resp), TIMEOUT_POWER_UP); if (!err) { v4l2_dbg(1, debug, &sdev->sd, "Powerup response: 0x%02x\n", resp[0]); v4l2_dbg(1, debug, &sdev->sd, "Device in power up mode\n"); sdev->power_state = POWER_ON; err = si4713_write_property(sdev, SI4713_GPO_IEN, SI4713_STC_INT | SI4713_CTS); } else { if (gpio_is_valid(sdev->gpio_reset)) gpio_set_value(sdev->gpio_reset, 0); err = regulator_bulk_disable(ARRAY_SIZE(sdev->supplies), sdev->supplies); if (err) v4l2_err(&sdev->sd, "Failed to disable supplies: %d\n", err); } return err; }
/* si4713_s_modulator - set modulator attributes */ static int si4713_s_modulator(struct v4l2_subdev *sd, struct v4l2_modulator *vm) { struct si4713_device *sdev = to_si4713_device(sd); int rval = 0; u16 stereo, rds; u32 p; if (!sdev) return -ENODEV; if (vm->index > 0) return -EINVAL; /* Set audio mode: mono or stereo */ if (vm->txsubchans & V4L2_TUNER_SUB_STEREO) stereo = 1; else if (vm->txsubchans & V4L2_TUNER_SUB_MONO) stereo = 0; else return -EINVAL; rds = !!(vm->txsubchans & V4L2_TUNER_SUB_RDS); mutex_lock(&sdev->mutex); if (sdev->power_state) { rval = si4713_read_property(sdev, SI4713_TX_COMPONENT_ENABLE, &p); if (rval < 0) goto unlock; p = set_bits(p, stereo, 1, 1 << 1); p = set_bits(p, rds, 2, 1 << 2); rval = si4713_write_property(sdev, SI4713_TX_COMPONENT_ENABLE, p); if (rval < 0) goto unlock; } sdev->stereo = stereo; sdev->rds_info.enabled = rds; unlock: mutex_unlock(&sdev->mutex); return rval; }
static int si4713_powerup(struct si4713_device *sdev) { int err; u8 resp[SI4713_PWUP_NRESP]; /* * .First byte = Enabled interrupts and boot function * .Second byte = Input operation mode */ const u8 args[SI4713_PWUP_NARGS] = { SI4713_PWUP_CTSIEN | SI4713_PWUP_GPO2OEN | SI4713_PWUP_FUNC_TX, SI4713_PWUP_OPMOD_ANALOG, }; if (sdev->power_state) return 0; sdev->platform_data->set_power(1); err = si4713_send_command(sdev, SI4713_CMD_POWER_UP, args, ARRAY_SIZE(args), resp, ARRAY_SIZE(resp), TIMEOUT_POWER_UP); if (!err) { v4l2_dbg(1, debug, &sdev->sd, "Powerup response: 0x%02x\n", resp[0]); v4l2_dbg(1, debug, &sdev->sd, "Device in power up mode\n"); sdev->power_state = POWER_ON; err = si4713_write_property(sdev, SI4713_GPO_IEN, SI4713_STC_INT | SI4713_CTS); } else { sdev->platform_data->set_power(0); } return err; }
/* si4713_s_ctrl - set the value of a control */ static int si4713_s_ctrl(struct v4l2_ctrl *ctrl) { struct si4713_device *sdev = container_of(ctrl->handler, struct si4713_device, ctrl_handler); u32 val = 0; s32 bit = 0, mask = 0; u16 property = 0; int mul = 0; unsigned long *table = NULL; int size = 0; bool force = false; int c; int ret = 0; if (ctrl->id != V4L2_CID_AUDIO_MUTE) return -EINVAL; if (ctrl->is_new) { if (ctrl->val) { ret = si4713_set_mute(sdev, ctrl->val); if (!ret) ret = si4713_set_power_state(sdev, POWER_DOWN); return ret; } ret = si4713_set_power_state(sdev, POWER_UP); if (!ret) ret = si4713_set_mute(sdev, ctrl->val); if (!ret) ret = si4713_setup(sdev); if (ret) return ret; force = true; } if (!sdev->power_state) return 0; for (c = 1; !ret && c < ctrl->ncontrols; c++) { ctrl = ctrl->cluster[c]; if (!force && !ctrl->is_new) continue; switch (ctrl->id) { case V4L2_CID_RDS_TX_PS_NAME: ret = si4713_set_rds_ps_name(sdev, ctrl->string); break; case V4L2_CID_RDS_TX_RADIO_TEXT: ret = si4713_set_rds_radio_text(sdev, ctrl->string); break; case V4L2_CID_TUNE_ANTENNA_CAPACITOR: /* don't handle this control if we force setting all * controls since in that case it will be handled by * V4L2_CID_TUNE_POWER_LEVEL. */ if (force) break; /* fall through */ case V4L2_CID_TUNE_POWER_LEVEL: ret = si4713_tx_tune_power(sdev, sdev->tune_pwr_level->val, sdev->tune_ant_cap->val); if (!ret) { /* Make sure we don't set this twice */ sdev->tune_ant_cap->is_new = false; sdev->tune_pwr_level->is_new = false; } break; default: ret = si4713_choose_econtrol_action(sdev, ctrl->id, &bit, &mask, &property, &mul, &table, &size); if (ret < 0) break; val = ctrl->val; if (mul) { val = val / mul; } else if (table) { ret = usecs_to_dev(val, table, size); if (ret < 0) break; val = ret; ret = 0; } if (mask) { ret = si4713_read_property(sdev, property, &val); if (ret < 0) break; val = set_bits(val, ctrl->val, bit, mask); } ret = si4713_write_property(sdev, property, val); if (ret < 0) break; if (mask) val = ctrl->val; break; } } return ret; }
/* * si4713_powerup - Powers the device up * @sdev: si4713_device structure for the device we are communicating */ static int si4713_powerup(struct si4713_device *sdev) { struct i2c_client *client = v4l2_get_subdevdata(&sdev->sd); int err; u8 resp[SI4713_PWUP_NRESP]; /* * .First byte = Enabled interrupts and boot function * .Second byte = Input operation mode */ u8 args[SI4713_PWUP_NARGS] = { SI4713_PWUP_GPO2OEN | SI4713_PWUP_FUNC_TX, SI4713_PWUP_OPMOD_ANALOG, }; if (sdev->power_state) return 0; if (sdev->vdd) { err = regulator_enable(sdev->vdd); if (err) { v4l2_err(&sdev->sd, "Failed to enable vdd: %d\n", err); return err; } } if (sdev->vio) { err = regulator_enable(sdev->vio); if (err) { v4l2_err(&sdev->sd, "Failed to enable vio: %d\n", err); return err; } } if (sdev->gpio_reset) { udelay(50); gpiod_set_value(sdev->gpio_reset, 1); } if (client->irq) args[0] |= SI4713_PWUP_CTSIEN; err = si4713_send_command(sdev, SI4713_CMD_POWER_UP, args, ARRAY_SIZE(args), resp, ARRAY_SIZE(resp), TIMEOUT_POWER_UP); if (!err) { v4l2_dbg(1, debug, &sdev->sd, "Powerup response: 0x%02x\n", resp[0]); v4l2_dbg(1, debug, &sdev->sd, "Device in power up mode\n"); sdev->power_state = POWER_ON; if (client->irq) err = si4713_write_property(sdev, SI4713_GPO_IEN, SI4713_STC_INT | SI4713_CTS); return err; } gpiod_set_value(sdev->gpio_reset, 0); if (sdev->vdd) { err = regulator_disable(sdev->vdd); if (err) v4l2_err(&sdev->sd, "Failed to disable vdd: %d\n", err); } if (sdev->vio) { err = regulator_disable(sdev->vio); if (err) v4l2_err(&sdev->sd, "Failed to disable vio: %d\n", err); } return err; }
static int si4713_write_econtrol_integers(struct si4713_device *sdev, struct v4l2_ext_control *control) { s32 rval; u32 *shadow = NULL, val = 0; s32 bit = 0, mask = 0; u16 property = 0; int mul = 0; unsigned long *table = NULL; int size = 0; rval = validate_range(&sdev->sd, control); if (rval < 0) goto exit; rval = si4713_choose_econtrol_action(sdev, control->id, &shadow, &bit, &mask, &property, &mul, &table, &size); if (rval < 0) goto exit; val = control->value; if (mul) { val = control->value / mul; } else if (table) { rval = usecs_to_dev(control->value, table, size); if (rval < 0) goto exit; val = rval; rval = 0; } mutex_lock(&sdev->mutex); if (sdev->power_state) { if (mask) { rval = si4713_read_property(sdev, property, &val); if (rval < 0) goto unlock; val = set_bits(val, control->value, bit, mask); } rval = si4713_write_property(sdev, property, val); if (rval < 0) goto unlock; if (mask) val = control->value; } if (mul) { *shadow = val * mul; } else if (table) { rval = dev_to_usecs(val, table, size); if (rval < 0) goto unlock; *shadow = rval; rval = 0; } else { *shadow = val; } unlock: mutex_unlock(&sdev->mutex); exit: return rval; }