Commit ac00b654 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'media/v6.8-4' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media

Pull media fixes from Mauro Carvalho Chehab:

 - regression fix for rkisp1 shared IRQ logic

 - fix atomisp breakage due to a kAPI change

 - permission fix for remote controller BPF support

 - memleak fix in ir_toy driver

 - Kconfig dependency fix for pwm-ir-rx

* tag 'media/v6.8-4' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media:
  media: pwm-ir-tx: Depend on CONFIG_HIGH_RES_TIMERS
  media: ir_toy: fix a memleak in irtoy_tx
  media: rc: bpf attach/detach requires write permission
  media: atomisp: Adjust for v4l2_subdev_state handling changes in 6.8
  media: rkisp1: Fix IRQ handling due to shared interrupts
  media: Revert "media: rkisp1: Drop IRQF_SHARED"
parents 4a757148 346c84e2
...@@ -725,6 +725,9 @@ irqreturn_t rkisp1_capture_isr(int irq, void *ctx) ...@@ -725,6 +725,9 @@ irqreturn_t rkisp1_capture_isr(int irq, void *ctx)
unsigned int i; unsigned int i;
u32 status; u32 status;
if (!rkisp1->irqs_enabled)
return IRQ_NONE;
status = rkisp1_read(rkisp1, RKISP1_CIF_MI_MIS); status = rkisp1_read(rkisp1, RKISP1_CIF_MI_MIS);
if (!status) if (!status)
return IRQ_NONE; return IRQ_NONE;
......
...@@ -450,6 +450,7 @@ struct rkisp1_debug { ...@@ -450,6 +450,7 @@ struct rkisp1_debug {
* @debug: debug params to be exposed on debugfs * @debug: debug params to be exposed on debugfs
* @info: version-specific ISP information * @info: version-specific ISP information
* @irqs: IRQ line numbers * @irqs: IRQ line numbers
* @irqs_enabled: the hardware is enabled and can cause interrupts
*/ */
struct rkisp1_device { struct rkisp1_device {
void __iomem *base_addr; void __iomem *base_addr;
...@@ -471,6 +472,7 @@ struct rkisp1_device { ...@@ -471,6 +472,7 @@ struct rkisp1_device {
struct rkisp1_debug debug; struct rkisp1_debug debug;
const struct rkisp1_info *info; const struct rkisp1_info *info;
int irqs[RKISP1_NUM_IRQS]; int irqs[RKISP1_NUM_IRQS];
bool irqs_enabled;
}; };
/* /*
......
...@@ -196,6 +196,9 @@ irqreturn_t rkisp1_csi_isr(int irq, void *ctx) ...@@ -196,6 +196,9 @@ irqreturn_t rkisp1_csi_isr(int irq, void *ctx)
struct rkisp1_device *rkisp1 = dev_get_drvdata(dev); struct rkisp1_device *rkisp1 = dev_get_drvdata(dev);
u32 val, status; u32 val, status;
if (!rkisp1->irqs_enabled)
return IRQ_NONE;
status = rkisp1_read(rkisp1, RKISP1_CIF_MIPI_MIS); status = rkisp1_read(rkisp1, RKISP1_CIF_MIPI_MIS);
if (!status) if (!status)
return IRQ_NONE; return IRQ_NONE;
......
...@@ -305,6 +305,24 @@ static int __maybe_unused rkisp1_runtime_suspend(struct device *dev) ...@@ -305,6 +305,24 @@ static int __maybe_unused rkisp1_runtime_suspend(struct device *dev)
{ {
struct rkisp1_device *rkisp1 = dev_get_drvdata(dev); struct rkisp1_device *rkisp1 = dev_get_drvdata(dev);
rkisp1->irqs_enabled = false;
/* Make sure the IRQ handler will see the above */
mb();
/*
* Wait until any running IRQ handler has returned. The IRQ handler
* may get called even after this (as it's a shared interrupt line)
* but the 'irqs_enabled' flag will make the handler return immediately.
*/
for (unsigned int il = 0; il < ARRAY_SIZE(rkisp1->irqs); ++il) {
if (rkisp1->irqs[il] == -1)
continue;
/* Skip if the irq line is the same as previous */
if (il == 0 || rkisp1->irqs[il - 1] != rkisp1->irqs[il])
synchronize_irq(rkisp1->irqs[il]);
}
clk_bulk_disable_unprepare(rkisp1->clk_size, rkisp1->clks); clk_bulk_disable_unprepare(rkisp1->clk_size, rkisp1->clks);
return pinctrl_pm_select_sleep_state(dev); return pinctrl_pm_select_sleep_state(dev);
} }
...@@ -321,6 +339,10 @@ static int __maybe_unused rkisp1_runtime_resume(struct device *dev) ...@@ -321,6 +339,10 @@ static int __maybe_unused rkisp1_runtime_resume(struct device *dev)
if (ret) if (ret)
return ret; return ret;
rkisp1->irqs_enabled = true;
/* Make sure the IRQ handler will see the above */
mb();
return 0; return 0;
} }
...@@ -559,7 +581,7 @@ static int rkisp1_probe(struct platform_device *pdev) ...@@ -559,7 +581,7 @@ static int rkisp1_probe(struct platform_device *pdev)
rkisp1->irqs[il] = irq; rkisp1->irqs[il] = irq;
} }
ret = devm_request_irq(dev, irq, info->isrs[i].isr, 0, ret = devm_request_irq(dev, irq, info->isrs[i].isr, IRQF_SHARED,
dev_driver_string(dev), dev); dev_driver_string(dev), dev);
if (ret) { if (ret) {
dev_err(dev, "request irq failed: %d\n", ret); dev_err(dev, "request irq failed: %d\n", ret);
......
...@@ -976,6 +976,9 @@ irqreturn_t rkisp1_isp_isr(int irq, void *ctx) ...@@ -976,6 +976,9 @@ irqreturn_t rkisp1_isp_isr(int irq, void *ctx)
struct rkisp1_device *rkisp1 = dev_get_drvdata(dev); struct rkisp1_device *rkisp1 = dev_get_drvdata(dev);
u32 status, isp_err; u32 status, isp_err;
if (!rkisp1->irqs_enabled)
return IRQ_NONE;
status = rkisp1_read(rkisp1, RKISP1_CIF_ISP_MIS); status = rkisp1_read(rkisp1, RKISP1_CIF_ISP_MIS);
if (!status) if (!status)
return IRQ_NONE; return IRQ_NONE;
......
...@@ -319,6 +319,7 @@ config IR_PWM_TX ...@@ -319,6 +319,7 @@ config IR_PWM_TX
tristate "PWM IR transmitter" tristate "PWM IR transmitter"
depends on LIRC depends on LIRC
depends on PWM depends on PWM
depends on HIGH_RES_TIMERS
depends on OF depends on OF
help help
Say Y if you want to use a PWM based IR transmitter. This is Say Y if you want to use a PWM based IR transmitter. This is
......
...@@ -253,7 +253,7 @@ int lirc_prog_attach(const union bpf_attr *attr, struct bpf_prog *prog) ...@@ -253,7 +253,7 @@ int lirc_prog_attach(const union bpf_attr *attr, struct bpf_prog *prog)
if (attr->attach_flags) if (attr->attach_flags)
return -EINVAL; return -EINVAL;
rcdev = rc_dev_get_from_fd(attr->target_fd); rcdev = rc_dev_get_from_fd(attr->target_fd, true);
if (IS_ERR(rcdev)) if (IS_ERR(rcdev))
return PTR_ERR(rcdev); return PTR_ERR(rcdev);
...@@ -278,7 +278,7 @@ int lirc_prog_detach(const union bpf_attr *attr) ...@@ -278,7 +278,7 @@ int lirc_prog_detach(const union bpf_attr *attr)
if (IS_ERR(prog)) if (IS_ERR(prog))
return PTR_ERR(prog); return PTR_ERR(prog);
rcdev = rc_dev_get_from_fd(attr->target_fd); rcdev = rc_dev_get_from_fd(attr->target_fd, true);
if (IS_ERR(rcdev)) { if (IS_ERR(rcdev)) {
bpf_prog_put(prog); bpf_prog_put(prog);
return PTR_ERR(rcdev); return PTR_ERR(rcdev);
...@@ -303,7 +303,7 @@ int lirc_prog_query(const union bpf_attr *attr, union bpf_attr __user *uattr) ...@@ -303,7 +303,7 @@ int lirc_prog_query(const union bpf_attr *attr, union bpf_attr __user *uattr)
if (attr->query.query_flags) if (attr->query.query_flags)
return -EINVAL; return -EINVAL;
rcdev = rc_dev_get_from_fd(attr->query.target_fd); rcdev = rc_dev_get_from_fd(attr->query.target_fd, false);
if (IS_ERR(rcdev)) if (IS_ERR(rcdev))
return PTR_ERR(rcdev); return PTR_ERR(rcdev);
......
...@@ -332,6 +332,7 @@ static int irtoy_tx(struct rc_dev *rc, uint *txbuf, uint count) ...@@ -332,6 +332,7 @@ static int irtoy_tx(struct rc_dev *rc, uint *txbuf, uint count)
sizeof(COMMAND_SMODE_EXIT), STATE_COMMAND_NO_RESP); sizeof(COMMAND_SMODE_EXIT), STATE_COMMAND_NO_RESP);
if (err) { if (err) {
dev_err(irtoy->dev, "exit sample mode: %d\n", err); dev_err(irtoy->dev, "exit sample mode: %d\n", err);
kfree(buf);
return err; return err;
} }
...@@ -339,6 +340,7 @@ static int irtoy_tx(struct rc_dev *rc, uint *txbuf, uint count) ...@@ -339,6 +340,7 @@ static int irtoy_tx(struct rc_dev *rc, uint *txbuf, uint count)
sizeof(COMMAND_SMODE_ENTER), STATE_COMMAND); sizeof(COMMAND_SMODE_ENTER), STATE_COMMAND);
if (err) { if (err) {
dev_err(irtoy->dev, "enter sample mode: %d\n", err); dev_err(irtoy->dev, "enter sample mode: %d\n", err);
kfree(buf);
return err; return err;
} }
......
...@@ -814,7 +814,7 @@ void __exit lirc_dev_exit(void) ...@@ -814,7 +814,7 @@ void __exit lirc_dev_exit(void)
unregister_chrdev_region(lirc_base_dev, RC_DEV_MAX); unregister_chrdev_region(lirc_base_dev, RC_DEV_MAX);
} }
struct rc_dev *rc_dev_get_from_fd(int fd) struct rc_dev *rc_dev_get_from_fd(int fd, bool write)
{ {
struct fd f = fdget(fd); struct fd f = fdget(fd);
struct lirc_fh *fh; struct lirc_fh *fh;
...@@ -828,6 +828,9 @@ struct rc_dev *rc_dev_get_from_fd(int fd) ...@@ -828,6 +828,9 @@ struct rc_dev *rc_dev_get_from_fd(int fd)
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
} }
if (write && !(f.file->f_mode & FMODE_WRITE))
return ERR_PTR(-EPERM);
fh = f.file->private_data; fh = f.file->private_data;
dev = fh->rc; dev = fh->rc;
......
...@@ -325,7 +325,7 @@ void lirc_raw_event(struct rc_dev *dev, struct ir_raw_event ev); ...@@ -325,7 +325,7 @@ void lirc_raw_event(struct rc_dev *dev, struct ir_raw_event ev);
void lirc_scancode_event(struct rc_dev *dev, struct lirc_scancode *lsc); void lirc_scancode_event(struct rc_dev *dev, struct lirc_scancode *lsc);
int lirc_register(struct rc_dev *dev); int lirc_register(struct rc_dev *dev);
void lirc_unregister(struct rc_dev *dev); void lirc_unregister(struct rc_dev *dev);
struct rc_dev *rc_dev_get_from_fd(int fd); struct rc_dev *rc_dev_get_from_fd(int fd, bool write);
#else #else
static inline int lirc_dev_init(void) { return 0; } static inline int lirc_dev_init(void) { return 0; }
static inline void lirc_dev_exit(void) {} static inline void lirc_dev_exit(void) {}
......
...@@ -3723,12 +3723,10 @@ void atomisp_get_padding(struct atomisp_device *isp, u32 width, u32 height, ...@@ -3723,12 +3723,10 @@ void atomisp_get_padding(struct atomisp_device *isp, u32 width, u32 height,
static int atomisp_set_crop(struct atomisp_device *isp, static int atomisp_set_crop(struct atomisp_device *isp,
const struct v4l2_mbus_framefmt *format, const struct v4l2_mbus_framefmt *format,
struct v4l2_subdev_state *sd_state,
int which) int which)
{ {
struct atomisp_input_subdev *input = &isp->inputs[isp->asd.input_curr]; struct atomisp_input_subdev *input = &isp->inputs[isp->asd.input_curr];
struct v4l2_subdev_state pad_state = {
.pads = &input->pad_cfg,
};
struct v4l2_subdev_selection sel = { struct v4l2_subdev_selection sel = {
.which = which, .which = which,
.target = V4L2_SEL_TGT_CROP, .target = V4L2_SEL_TGT_CROP,
...@@ -3754,7 +3752,7 @@ static int atomisp_set_crop(struct atomisp_device *isp, ...@@ -3754,7 +3752,7 @@ static int atomisp_set_crop(struct atomisp_device *isp,
sel.r.left = ((input->native_rect.width - sel.r.width) / 2) & ~1; sel.r.left = ((input->native_rect.width - sel.r.width) / 2) & ~1;
sel.r.top = ((input->native_rect.height - sel.r.height) / 2) & ~1; sel.r.top = ((input->native_rect.height - sel.r.height) / 2) & ~1;
ret = v4l2_subdev_call(input->camera, pad, set_selection, &pad_state, &sel); ret = v4l2_subdev_call(input->camera, pad, set_selection, sd_state, &sel);
if (ret) if (ret)
dev_err(isp->dev, "Error setting crop to %ux%u @%ux%u: %d\n", dev_err(isp->dev, "Error setting crop to %ux%u @%ux%u: %d\n",
sel.r.width, sel.r.height, sel.r.left, sel.r.top, ret); sel.r.width, sel.r.height, sel.r.left, sel.r.top, ret);
...@@ -3770,9 +3768,6 @@ int atomisp_try_fmt(struct atomisp_device *isp, struct v4l2_pix_format *f, ...@@ -3770,9 +3768,6 @@ int atomisp_try_fmt(struct atomisp_device *isp, struct v4l2_pix_format *f,
const struct atomisp_format_bridge *fmt, *snr_fmt; const struct atomisp_format_bridge *fmt, *snr_fmt;
struct atomisp_sub_device *asd = &isp->asd; struct atomisp_sub_device *asd = &isp->asd;
struct atomisp_input_subdev *input = &isp->inputs[asd->input_curr]; struct atomisp_input_subdev *input = &isp->inputs[asd->input_curr];
struct v4l2_subdev_state pad_state = {
.pads = &input->pad_cfg,
};
struct v4l2_subdev_format format = { struct v4l2_subdev_format format = {
.which = V4L2_SUBDEV_FORMAT_TRY, .which = V4L2_SUBDEV_FORMAT_TRY,
}; };
...@@ -3809,11 +3804,16 @@ int atomisp_try_fmt(struct atomisp_device *isp, struct v4l2_pix_format *f, ...@@ -3809,11 +3804,16 @@ int atomisp_try_fmt(struct atomisp_device *isp, struct v4l2_pix_format *f,
dev_dbg(isp->dev, "try_mbus_fmt: asking for %ux%u\n", dev_dbg(isp->dev, "try_mbus_fmt: asking for %ux%u\n",
format.format.width, format.format.height); format.format.width, format.format.height);
ret = atomisp_set_crop(isp, &format.format, V4L2_SUBDEV_FORMAT_TRY); v4l2_subdev_lock_state(input->try_sd_state);
if (ret)
return ret; ret = atomisp_set_crop(isp, &format.format, input->try_sd_state,
V4L2_SUBDEV_FORMAT_TRY);
if (ret == 0)
ret = v4l2_subdev_call(input->camera, pad, set_fmt,
input->try_sd_state, &format);
v4l2_subdev_unlock_state(input->try_sd_state);
ret = v4l2_subdev_call(input->camera, pad, set_fmt, &pad_state, &format);
if (ret) if (ret)
return ret; return ret;
...@@ -4238,9 +4238,7 @@ static int atomisp_set_fmt_to_snr(struct video_device *vdev, const struct v4l2_p ...@@ -4238,9 +4238,7 @@ static int atomisp_set_fmt_to_snr(struct video_device *vdev, const struct v4l2_p
struct atomisp_device *isp = asd->isp; struct atomisp_device *isp = asd->isp;
struct atomisp_input_subdev *input = &isp->inputs[asd->input_curr]; struct atomisp_input_subdev *input = &isp->inputs[asd->input_curr];
const struct atomisp_format_bridge *format; const struct atomisp_format_bridge *format;
struct v4l2_subdev_state pad_state = { struct v4l2_subdev_state *act_sd_state;
.pads = &input->pad_cfg,
};
struct v4l2_subdev_format vformat = { struct v4l2_subdev_format vformat = {
.which = V4L2_SUBDEV_FORMAT_TRY, .which = V4L2_SUBDEV_FORMAT_TRY,
}; };
...@@ -4268,12 +4266,18 @@ static int atomisp_set_fmt_to_snr(struct video_device *vdev, const struct v4l2_p ...@@ -4268,12 +4266,18 @@ static int atomisp_set_fmt_to_snr(struct video_device *vdev, const struct v4l2_p
/* Disable dvs if resolution can't be supported by sensor */ /* Disable dvs if resolution can't be supported by sensor */
if (asd->params.video_dis_en && asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO) { if (asd->params.video_dis_en && asd->run_mode->val == ATOMISP_RUN_MODE_VIDEO) {
ret = atomisp_set_crop(isp, &vformat.format, V4L2_SUBDEV_FORMAT_TRY); v4l2_subdev_lock_state(input->try_sd_state);
if (ret)
return ret; ret = atomisp_set_crop(isp, &vformat.format, input->try_sd_state,
V4L2_SUBDEV_FORMAT_TRY);
if (ret == 0) {
vformat.which = V4L2_SUBDEV_FORMAT_TRY;
ret = v4l2_subdev_call(input->camera, pad, set_fmt,
input->try_sd_state, &vformat);
}
v4l2_subdev_unlock_state(input->try_sd_state);
vformat.which = V4L2_SUBDEV_FORMAT_TRY;
ret = v4l2_subdev_call(input->camera, pad, set_fmt, &pad_state, &vformat);
if (ret) if (ret)
return ret; return ret;
...@@ -4291,12 +4295,18 @@ static int atomisp_set_fmt_to_snr(struct video_device *vdev, const struct v4l2_p ...@@ -4291,12 +4295,18 @@ static int atomisp_set_fmt_to_snr(struct video_device *vdev, const struct v4l2_p
} }
} }
ret = atomisp_set_crop(isp, &vformat.format, V4L2_SUBDEV_FORMAT_ACTIVE); act_sd_state = v4l2_subdev_lock_and_get_active_state(input->camera);
if (ret)
return ret; ret = atomisp_set_crop(isp, &vformat.format, act_sd_state,
V4L2_SUBDEV_FORMAT_ACTIVE);
if (ret == 0) {
vformat.which = V4L2_SUBDEV_FORMAT_ACTIVE;
ret = v4l2_subdev_call(input->camera, pad, set_fmt, act_sd_state, &vformat);
}
if (act_sd_state)
v4l2_subdev_unlock_state(act_sd_state);
vformat.which = V4L2_SUBDEV_FORMAT_ACTIVE;
ret = v4l2_subdev_call(input->camera, pad, set_fmt, NULL, &vformat);
if (ret) if (ret)
return ret; return ret;
......
...@@ -132,8 +132,8 @@ struct atomisp_input_subdev { ...@@ -132,8 +132,8 @@ struct atomisp_input_subdev {
/* Sensor rects for sensors which support crop */ /* Sensor rects for sensors which support crop */
struct v4l2_rect native_rect; struct v4l2_rect native_rect;
struct v4l2_rect active_rect; struct v4l2_rect active_rect;
/* Sensor pad_cfg for which == V4L2_SUBDEV_FORMAT_TRY calls */ /* Sensor state for which == V4L2_SUBDEV_FORMAT_TRY calls */
struct v4l2_subdev_pad_config pad_cfg; struct v4l2_subdev_state *try_sd_state;
struct v4l2_subdev *motor; struct v4l2_subdev *motor;
......
...@@ -781,12 +781,20 @@ static int atomisp_enum_framesizes(struct file *file, void *priv, ...@@ -781,12 +781,20 @@ static int atomisp_enum_framesizes(struct file *file, void *priv,
.which = V4L2_SUBDEV_FORMAT_ACTIVE, .which = V4L2_SUBDEV_FORMAT_ACTIVE,
.code = input->code, .code = input->code,
}; };
struct v4l2_subdev_state *act_sd_state;
int ret; int ret;
if (!input->camera)
return -EINVAL;
if (input->crop_support) if (input->crop_support)
return atomisp_enum_framesizes_crop(isp, fsize); return atomisp_enum_framesizes_crop(isp, fsize);
ret = v4l2_subdev_call(input->camera, pad, enum_frame_size, NULL, &fse); act_sd_state = v4l2_subdev_lock_and_get_active_state(input->camera);
ret = v4l2_subdev_call(input->camera, pad, enum_frame_size,
act_sd_state, &fse);
if (act_sd_state)
v4l2_subdev_unlock_state(act_sd_state);
if (ret) if (ret)
return ret; return ret;
...@@ -803,18 +811,25 @@ static int atomisp_enum_frameintervals(struct file *file, void *priv, ...@@ -803,18 +811,25 @@ static int atomisp_enum_frameintervals(struct file *file, void *priv,
struct video_device *vdev = video_devdata(file); struct video_device *vdev = video_devdata(file);
struct atomisp_device *isp = video_get_drvdata(vdev); struct atomisp_device *isp = video_get_drvdata(vdev);
struct atomisp_sub_device *asd = atomisp_to_video_pipe(vdev)->asd; struct atomisp_sub_device *asd = atomisp_to_video_pipe(vdev)->asd;
struct atomisp_input_subdev *input = &isp->inputs[asd->input_curr];
struct v4l2_subdev_frame_interval_enum fie = { struct v4l2_subdev_frame_interval_enum fie = {
.code = atomisp_in_fmt_conv[0].code, .code = atomisp_in_fmt_conv[0].code,
.index = fival->index, .index = fival->index,
.width = fival->width, .width = fival->width,
.height = fival->height, .height = fival->height,
.which = V4L2_SUBDEV_FORMAT_ACTIVE, .which = V4L2_SUBDEV_FORMAT_ACTIVE,
}; };
struct v4l2_subdev_state *act_sd_state;
int ret; int ret;
ret = v4l2_subdev_call(isp->inputs[asd->input_curr].camera, if (!input->camera)
pad, enum_frame_interval, NULL, return -EINVAL;
&fie);
act_sd_state = v4l2_subdev_lock_and_get_active_state(input->camera);
ret = v4l2_subdev_call(input->camera, pad, enum_frame_interval,
act_sd_state, &fie);
if (act_sd_state)
v4l2_subdev_unlock_state(act_sd_state);
if (ret) if (ret)
return ret; return ret;
...@@ -830,30 +845,25 @@ static int atomisp_enum_fmt_cap(struct file *file, void *fh, ...@@ -830,30 +845,25 @@ static int atomisp_enum_fmt_cap(struct file *file, void *fh,
struct video_device *vdev = video_devdata(file); struct video_device *vdev = video_devdata(file);
struct atomisp_device *isp = video_get_drvdata(vdev); struct atomisp_device *isp = video_get_drvdata(vdev);
struct atomisp_sub_device *asd = atomisp_to_video_pipe(vdev)->asd; struct atomisp_sub_device *asd = atomisp_to_video_pipe(vdev)->asd;
struct atomisp_input_subdev *input = &isp->inputs[asd->input_curr];
struct v4l2_subdev_mbus_code_enum code = { struct v4l2_subdev_mbus_code_enum code = {
.which = V4L2_SUBDEV_FORMAT_ACTIVE, .which = V4L2_SUBDEV_FORMAT_ACTIVE,
}; };
const struct atomisp_format_bridge *format; const struct atomisp_format_bridge *format;
struct v4l2_subdev *camera; struct v4l2_subdev_state *act_sd_state;
unsigned int i, fi = 0; unsigned int i, fi = 0;
int rval; int ret;
camera = isp->inputs[asd->input_curr].camera; if (!input->camera)
if(!camera) {
dev_err(isp->dev, "%s(): camera is NULL, device is %s\n",
__func__, vdev->name);
return -EINVAL; return -EINVAL;
}
rval = v4l2_subdev_call(camera, pad, enum_mbus_code, NULL, &code); act_sd_state = v4l2_subdev_lock_and_get_active_state(input->camera);
if (rval == -ENOIOCTLCMD) { ret = v4l2_subdev_call(input->camera, pad, enum_mbus_code,
dev_warn(isp->dev, act_sd_state, &code);
"enum_mbus_code pad op not supported by %s. Please fix your sensor driver!\n", if (act_sd_state)
camera->name); v4l2_subdev_unlock_state(act_sd_state);
} if (ret)
return ret;
if (rval)
return rval;
for (i = 0; i < ARRAY_SIZE(atomisp_output_fmts); i++) { for (i = 0; i < ARRAY_SIZE(atomisp_output_fmts); i++) {
format = &atomisp_output_fmts[i]; format = &atomisp_output_fmts[i];
......
...@@ -862,6 +862,9 @@ static void atomisp_unregister_entities(struct atomisp_device *isp) ...@@ -862,6 +862,9 @@ static void atomisp_unregister_entities(struct atomisp_device *isp)
v4l2_device_unregister(&isp->v4l2_dev); v4l2_device_unregister(&isp->v4l2_dev);
media_device_unregister(&isp->media_dev); media_device_unregister(&isp->media_dev);
media_device_cleanup(&isp->media_dev); media_device_cleanup(&isp->media_dev);
for (i = 0; i < isp->input_cnt; i++)
__v4l2_subdev_state_free(isp->inputs[i].try_sd_state);
} }
static int atomisp_register_entities(struct atomisp_device *isp) static int atomisp_register_entities(struct atomisp_device *isp)
...@@ -933,32 +936,49 @@ static int atomisp_register_entities(struct atomisp_device *isp) ...@@ -933,32 +936,49 @@ static int atomisp_register_entities(struct atomisp_device *isp)
static void atomisp_init_sensor(struct atomisp_input_subdev *input) static void atomisp_init_sensor(struct atomisp_input_subdev *input)
{ {
static struct lock_class_key try_sd_state_key;
struct v4l2_subdev_mbus_code_enum mbus_code_enum = { }; struct v4l2_subdev_mbus_code_enum mbus_code_enum = { };
struct v4l2_subdev_frame_size_enum fse = { }; struct v4l2_subdev_frame_size_enum fse = { };
struct v4l2_subdev_state sd_state = {
.pads = &input->pad_cfg,
};
struct v4l2_subdev_selection sel = { }; struct v4l2_subdev_selection sel = { };
struct v4l2_subdev_state *try_sd_state, *act_sd_state;
int i, err; int i, err;
/*
* FIXME: Drivers are not supposed to use __v4l2_subdev_state_alloc()
* but atomisp needs this for try_fmt on its /dev/video# node since
* it emulates a normal v4l2 device there, passing through try_fmt /
* set_fmt to the sensor.
*/
try_sd_state = __v4l2_subdev_state_alloc(input->camera,
"atomisp:try_sd_state->lock", &try_sd_state_key);
if (IS_ERR(try_sd_state))
return;
input->try_sd_state = try_sd_state;
act_sd_state = v4l2_subdev_lock_and_get_active_state(input->camera);
mbus_code_enum.which = V4L2_SUBDEV_FORMAT_ACTIVE; mbus_code_enum.which = V4L2_SUBDEV_FORMAT_ACTIVE;
err = v4l2_subdev_call(input->camera, pad, enum_mbus_code, NULL, &mbus_code_enum); err = v4l2_subdev_call(input->camera, pad, enum_mbus_code,
act_sd_state, &mbus_code_enum);
if (!err) if (!err)
input->code = mbus_code_enum.code; input->code = mbus_code_enum.code;
sel.which = V4L2_SUBDEV_FORMAT_ACTIVE; sel.which = V4L2_SUBDEV_FORMAT_ACTIVE;
sel.target = V4L2_SEL_TGT_NATIVE_SIZE; sel.target = V4L2_SEL_TGT_NATIVE_SIZE;
err = v4l2_subdev_call(input->camera, pad, get_selection, NULL, &sel); err = v4l2_subdev_call(input->camera, pad, get_selection,
act_sd_state, &sel);
if (err) if (err)
return; goto unlock_act_sd_state;
input->native_rect = sel.r; input->native_rect = sel.r;
sel.which = V4L2_SUBDEV_FORMAT_ACTIVE; sel.which = V4L2_SUBDEV_FORMAT_ACTIVE;
sel.target = V4L2_SEL_TGT_CROP_DEFAULT; sel.target = V4L2_SEL_TGT_CROP_DEFAULT;
err = v4l2_subdev_call(input->camera, pad, get_selection, NULL, &sel); err = v4l2_subdev_call(input->camera, pad, get_selection,
act_sd_state, &sel);
if (err) if (err)
return; goto unlock_act_sd_state;
input->active_rect = sel.r; input->active_rect = sel.r;
...@@ -973,7 +993,8 @@ static void atomisp_init_sensor(struct atomisp_input_subdev *input) ...@@ -973,7 +993,8 @@ static void atomisp_init_sensor(struct atomisp_input_subdev *input)
fse.code = input->code; fse.code = input->code;
fse.which = V4L2_SUBDEV_FORMAT_ACTIVE; fse.which = V4L2_SUBDEV_FORMAT_ACTIVE;
err = v4l2_subdev_call(input->camera, pad, enum_frame_size, NULL, &fse); err = v4l2_subdev_call(input->camera, pad, enum_frame_size,
act_sd_state, &fse);
if (err) if (err)
break; break;
...@@ -989,22 +1010,26 @@ static void atomisp_init_sensor(struct atomisp_input_subdev *input) ...@@ -989,22 +1010,26 @@ static void atomisp_init_sensor(struct atomisp_input_subdev *input)
* for padding, set the crop rect to cover the entire sensor instead * for padding, set the crop rect to cover the entire sensor instead
* of only the default active area. * of only the default active area.
* *
* Do this for both try and active formats since the try_crop rect in * Do this for both try and active formats since the crop rect in
* pad_cfg may influence (clamp) future try_fmt calls with which == try. * try_sd_state may influence (clamp size) in calls with which == try.
*/ */
sel.which = V4L2_SUBDEV_FORMAT_TRY; sel.which = V4L2_SUBDEV_FORMAT_TRY;
sel.target = V4L2_SEL_TGT_CROP; sel.target = V4L2_SEL_TGT_CROP;
sel.r = input->native_rect; sel.r = input->native_rect;
err = v4l2_subdev_call(input->camera, pad, set_selection, &sd_state, &sel); v4l2_subdev_lock_state(input->try_sd_state);
err = v4l2_subdev_call(input->camera, pad, set_selection,
input->try_sd_state, &sel);
v4l2_subdev_unlock_state(input->try_sd_state);
if (err) if (err)
return; goto unlock_act_sd_state;
sel.which = V4L2_SUBDEV_FORMAT_ACTIVE; sel.which = V4L2_SUBDEV_FORMAT_ACTIVE;
sel.target = V4L2_SEL_TGT_CROP; sel.target = V4L2_SEL_TGT_CROP;
sel.r = input->native_rect; sel.r = input->native_rect;
err = v4l2_subdev_call(input->camera, pad, set_selection, NULL, &sel); err = v4l2_subdev_call(input->camera, pad, set_selection,
act_sd_state, &sel);
if (err) if (err)
return; goto unlock_act_sd_state;
dev_info(input->camera->dev, "Supports crop native %dx%d active %dx%d binning %d\n", dev_info(input->camera->dev, "Supports crop native %dx%d active %dx%d binning %d\n",
input->native_rect.width, input->native_rect.height, input->native_rect.width, input->native_rect.height,
...@@ -1012,6 +1037,10 @@ static void atomisp_init_sensor(struct atomisp_input_subdev *input) ...@@ -1012,6 +1037,10 @@ static void atomisp_init_sensor(struct atomisp_input_subdev *input)
input->binning_support); input->binning_support);
input->crop_support = true; input->crop_support = true;
unlock_act_sd_state:
if (act_sd_state)
v4l2_subdev_unlock_state(act_sd_state);
} }
int atomisp_register_device_nodes(struct atomisp_device *isp) int atomisp_register_device_nodes(struct atomisp_device *isp)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment