Lines Matching +full:- +full:state
1 // SPDX-License-Identifier: GPL-2.0-only
3 * Samsung S5P/EXYNOS SoC series MIPI-CSI receiver driver
5 * Copyright (C) 2011 - 2013 Samsung Electronics Co., Ltd.
29 #include <media/drv-intf/exynos-fimc.h>
30 #include <media/v4l2-fwnode.h>
31 #include <media/v4l2-subdev.h>
33 #include "mipi-csis.h"
37 MODULE_PARM_DESC(debug, "Debug level (0-2)");
51 /* D-PHY control */
62 #define S5PCSIS_CFG_FMT_USER(x) ((0x30 + x - 1) << 2)
109 /* Non-image packet data buffers */
153 /* Non-image data receive events */
154 { S5PCSIS_INTSRC_EVEN_BEFORE, "Non-image data before even frame" },
155 { S5PCSIS_INTSRC_EVEN_AFTER, "Non-image data after even frame" },
156 { S5PCSIS_INTSRC_ODD_BEFORE, "Non-image data before odd frame" },
157 { S5PCSIS_INTSRC_ODD_AFTER, "Non-image data after odd frame" },
175 * struct csis_state - the driver's internal state data structure
186 * @irq: requested s5p-mipi-csis irq number
188 * @flags: the state variable for power and streaming control
190 * @hs_settle: HS-RX settle time
191 * @num_lanes: number of MIPI-CSI data lanes used
192 * @max_num_lanes: maximum number of MIPI-CSI data lanes supported
193 * @wclk_ext: CSI wrapper clock: 0 - bus clock, 1 - external SCLK_CAM
197 * @pkt_buf: the frame embedded (non-image) data buffer
198 * @events: MIPI-CSIS event (error) counters
229 * struct csis_pix_format - CSIS pixel format description
234 * @data_alignment: MIPI-CSI data alignment in bits
271 #define s5pcsis_write(__csis, __r, __v) writel(__v, __csis->regs + __r)
272 #define s5pcsis_read(__csis, __r) readl(__csis->regs + __r)
285 if (mf->code == s5pcsis_formats[i].code)
290 static void s5pcsis_enable_interrupts(struct csis_state *state, bool on)
292 u32 val = s5pcsis_read(state, S5PCSIS_INTMSK);
294 val |= state->interrupt_mask;
296 val &= ~state->interrupt_mask;
297 s5pcsis_write(state, S5PCSIS_INTMSK, val);
300 static void s5pcsis_reset(struct csis_state *state)
302 u32 val = s5pcsis_read(state, S5PCSIS_CTRL);
304 s5pcsis_write(state, S5PCSIS_CTRL, val | S5PCSIS_CTRL_RESET);
308 static void s5pcsis_system_enable(struct csis_state *state, int on)
312 val = s5pcsis_read(state, S5PCSIS_CTRL);
317 s5pcsis_write(state, S5PCSIS_CTRL, val);
319 val = s5pcsis_read(state, S5PCSIS_DPHYCTRL);
322 mask = (1 << (state->num_lanes + 1)) - 1;
325 s5pcsis_write(state, S5PCSIS_DPHYCTRL, val);
328 /* Called with the state.lock mutex held */
329 static void __s5pcsis_set_format(struct csis_state *state)
331 struct v4l2_mbus_framefmt *mf = &state->format;
334 v4l2_dbg(1, debug, &state->sd, "fmt: %#x, %d x %d\n",
335 mf->code, mf->width, mf->height);
338 val = s5pcsis_read(state, S5PCSIS_CONFIG);
339 val = (val & ~S5PCSIS_CFG_FMT_MASK) | state->csis_fmt->fmt_reg;
340 s5pcsis_write(state, S5PCSIS_CONFIG, val);
343 val = (mf->width << 16) | mf->height;
344 s5pcsis_write(state, S5PCSIS_RESOL, val);
347 static void s5pcsis_set_hsync_settle(struct csis_state *state, int settle)
349 u32 val = s5pcsis_read(state, S5PCSIS_DPHYCTRL);
352 s5pcsis_write(state, S5PCSIS_DPHYCTRL, val);
355 static void s5pcsis_set_params(struct csis_state *state)
359 val = s5pcsis_read(state, S5PCSIS_CONFIG);
360 val = (val & ~S5PCSIS_CFG_NR_LANE_MASK) | (state->num_lanes - 1);
361 s5pcsis_write(state, S5PCSIS_CONFIG, val);
363 __s5pcsis_set_format(state);
364 s5pcsis_set_hsync_settle(state, state->hs_settle);
366 val = s5pcsis_read(state, S5PCSIS_CTRL);
367 if (state->csis_fmt->data_alignment == 32)
369 else /* 24-bits */
373 if (state->wclk_ext)
375 s5pcsis_write(state, S5PCSIS_CTRL, val);
378 val = s5pcsis_read(state, S5PCSIS_CTRL);
379 s5pcsis_write(state, S5PCSIS_CTRL, val | S5PCSIS_CTRL_UPDATE_SHADOW);
382 static void s5pcsis_clk_put(struct csis_state *state)
387 if (IS_ERR(state->clock[i]))
389 clk_unprepare(state->clock[i]);
390 clk_put(state->clock[i]);
391 state->clock[i] = ERR_PTR(-EINVAL);
395 static int s5pcsis_clk_get(struct csis_state *state)
397 struct device *dev = &state->pdev->dev;
401 state->clock[i] = ERR_PTR(-EINVAL);
404 state->clock[i] = clk_get(dev, csi_clock_name[i]);
405 if (IS_ERR(state->clock[i])) {
406 ret = PTR_ERR(state->clock[i]);
409 ret = clk_prepare(state->clock[i]);
411 clk_put(state->clock[i]);
412 state->clock[i] = ERR_PTR(-EINVAL);
418 s5pcsis_clk_put(state);
423 static void dump_regs(struct csis_state *state, const char *label)
439 v4l2_info(&state->sd, "--- %s ---\n", label);
442 u32 cfg = s5pcsis_read(state, registers[i].offset);
443 v4l2_info(&state->sd, "%10s: 0x%08x\n", registers[i].name, cfg);
447 static void s5pcsis_start_stream(struct csis_state *state)
449 s5pcsis_reset(state);
450 s5pcsis_set_params(state);
451 s5pcsis_system_enable(state, true);
452 s5pcsis_enable_interrupts(state, true);
455 static void s5pcsis_stop_stream(struct csis_state *state)
457 s5pcsis_enable_interrupts(state, false);
458 s5pcsis_system_enable(state, false);
461 static void s5pcsis_clear_counters(struct csis_state *state)
466 spin_lock_irqsave(&state->slock, flags);
468 state->events[i].counter = 0;
469 spin_unlock_irqrestore(&state->slock, flags);
472 static void s5pcsis_log_counters(struct csis_state *state, bool non_errors)
474 int i = non_errors ? S5PCSIS_NUM_EVENTS : S5PCSIS_NUM_EVENTS - 4;
477 spin_lock_irqsave(&state->slock, flags);
479 for (i--; i >= 0; i--) {
480 if (state->events[i].counter > 0 || debug)
481 v4l2_info(&state->sd, "%s events: %d\n",
482 state->events[i].name,
483 state->events[i].counter);
485 spin_unlock_irqrestore(&state->slock, flags);
493 struct csis_state *state = sd_to_csis_state(sd);
494 struct device *dev = &state->pdev->dev;
504 struct csis_state *state = sd_to_csis_state(sd);
507 v4l2_dbg(1, debug, sd, "%s: %d, state: 0x%x\n",
508 __func__, enable, state->flags);
511 s5pcsis_clear_counters(state);
512 ret = pm_runtime_resume_and_get(&state->pdev->dev);
517 mutex_lock(&state->lock);
519 if (state->flags & ST_SUSPENDED) {
520 ret = -EBUSY;
523 s5pcsis_start_stream(state);
524 state->flags |= ST_STREAMING;
526 s5pcsis_stop_stream(state);
527 state->flags &= ~ST_STREAMING;
529 s5pcsis_log_counters(state, true);
532 mutex_unlock(&state->lock);
534 pm_runtime_put(&state->pdev->dev);
543 if (code->index >= ARRAY_SIZE(s5pcsis_formats))
544 return -EINVAL;
546 code->code = s5pcsis_formats[code->index].code;
559 mf->code = csis_fmt->code;
560 v4l_bound_align_image(&mf->width, 1, CSIS_MAX_PIX_WIDTH,
561 csis_fmt->pix_width_alignment,
562 &mf->height, 1, CSIS_MAX_PIX_HEIGHT, 1,
568 struct csis_state *state, struct v4l2_subdev_state *sd_state,
574 return &state->format;
581 struct csis_state *state = sd_to_csis_state(sd);
585 mf = __s5pcsis_get_format(state, sd_state, fmt->which);
587 if (fmt->pad == CSIS_PAD_SOURCE) {
589 mutex_lock(&state->lock);
590 fmt->format = *mf;
591 mutex_unlock(&state->lock);
595 csis_fmt = s5pcsis_try_format(&fmt->format);
597 mutex_lock(&state->lock);
598 *mf = fmt->format;
599 if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE)
600 state->csis_fmt = csis_fmt;
601 mutex_unlock(&state->lock);
610 struct csis_state *state = sd_to_csis_state(sd);
613 mf = __s5pcsis_get_format(state, sd_state, fmt->which);
615 return -EINVAL;
617 mutex_lock(&state->lock);
618 fmt->format = *mf;
619 mutex_unlock(&state->lock);
626 struct csis_state *state = sd_to_csis_state(sd);
631 spin_lock_irqsave(&state->slock, flags);
632 state->pkt_buf.data = buf;
633 state->pkt_buf.len = *size;
634 spin_unlock_irqrestore(&state->slock, flags);
641 struct csis_state *state = sd_to_csis_state(sd);
643 mutex_lock(&state->lock);
644 s5pcsis_log_counters(state, true);
645 if (debug && (state->flags & ST_POWERED))
646 dump_regs(state, __func__);
647 mutex_unlock(&state->lock);
675 struct csis_state *state = dev_id;
676 struct csis_pktbuf *pktbuf = &state->pkt_buf;
680 status = s5pcsis_read(state, S5PCSIS_INTSRC);
681 spin_lock_irqsave(&state->slock, flags);
683 if ((status & S5PCSIS_INTSRC_NON_IMAGE_DATA) && pktbuf->data) {
691 memcpy(pktbuf->data, (u8 __force *)state->regs + offset,
692 pktbuf->len);
693 pktbuf->data = NULL;
701 if (!(status & state->events[i].mask))
703 state->events[i].counter++;
704 v4l2_dbg(2, debug, &state->sd, "%s: %d\n",
705 state->events[i].name,
706 state->events[i].counter);
708 v4l2_dbg(2, debug, &state->sd, "status: %08x\n", status);
710 spin_unlock_irqrestore(&state->slock, flags);
712 s5pcsis_write(state, S5PCSIS_INTSRC, status);
717 struct csis_state *state)
719 struct device_node *node = pdev->dev.of_node;
723 if (of_property_read_u32(node, "clock-frequency",
724 &state->clk_frequency))
725 state->clk_frequency = DEFAULT_SCLK_CSIS_FREQ;
726 if (of_property_read_u32(node, "bus-width",
727 &state->max_num_lanes))
728 return -EINVAL;
731 node = of_graph_get_endpoint_by_regs(node, -1, -1);
733 dev_err(&pdev->dev, "No port node at %pOF\n",
734 pdev->dev.of_node);
735 return -EINVAL;
737 /* Get port node and validate MIPI-CSI channel id. */
742 state->index = endpoint.base.port - FIMC_INPUT_MIPI_CSI2_0;
743 if (state->index >= CSIS_MAX_ENTITIES) {
744 ret = -ENXIO;
748 /* Get MIPI CSI-2 bus configuration from the endpoint node. */
749 of_property_read_u32(node, "samsung,csis-hs-settle",
750 &state->hs_settle);
751 state->wclk_ext = of_property_read_bool(node,
752 "samsung,csis-wclk");
754 state->num_lanes = endpoint.bus.mipi_csi2.num_data_lanes;
768 struct device *dev = &pdev->dev;
769 struct csis_state *state;
770 int ret = -ENOMEM;
773 state = devm_kzalloc(dev, sizeof(*state), GFP_KERNEL);
774 if (!state)
775 return -ENOMEM;
777 mutex_init(&state->lock);
778 spin_lock_init(&state->slock);
779 state->pdev = pdev;
781 of_id = of_match_node(s5pcsis_of_match, dev->of_node);
783 return -EINVAL;
785 drv_data = of_id->data;
786 state->interrupt_mask = drv_data->interrupt_mask;
788 ret = s5pcsis_parse_dt(pdev, state);
792 if (state->num_lanes == 0 || state->num_lanes > state->max_num_lanes) {
794 state->num_lanes, state->max_num_lanes);
795 return -EINVAL;
798 state->phy = devm_phy_get(dev, "csis");
799 if (IS_ERR(state->phy))
800 return PTR_ERR(state->phy);
802 state->regs = devm_platform_ioremap_resource(pdev, 0);
803 if (IS_ERR(state->regs))
804 return PTR_ERR(state->regs);
806 state->irq = platform_get_irq(pdev, 0);
807 if (state->irq < 0)
808 return state->irq;
811 state->supplies[i].supply = csis_supply_name[i];
814 state->supplies);
818 ret = s5pcsis_clk_get(state);
822 if (state->clk_frequency)
823 ret = clk_set_rate(state->clock[CSIS_CLK_MUX],
824 state->clk_frequency);
830 ret = clk_enable(state->clock[CSIS_CLK_MUX]);
834 ret = devm_request_irq(dev, state->irq, s5pcsis_irq_handler,
835 0, dev_name(dev), state);
841 v4l2_subdev_init(&state->sd, &s5pcsis_subdev_ops);
842 state->sd.owner = THIS_MODULE;
843 snprintf(state->sd.name, sizeof(state->sd.name), "%s.%d",
844 CSIS_SUBDEV_NAME, state->index);
845 state->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
846 state->csis_fmt = &s5pcsis_formats[0];
848 state->format.code = s5pcsis_formats[0].code;
849 state->format.width = S5PCSIS_DEF_PIX_WIDTH;
850 state->format.height = S5PCSIS_DEF_PIX_HEIGHT;
852 state->sd.entity.function = MEDIA_ENT_F_IO_V4L;
853 state->pads[CSIS_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
854 state->pads[CSIS_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
855 ret = media_entity_pads_init(&state->sd.entity,
856 CSIS_PADS_NUM, state->pads);
861 v4l2_set_subdevdata(&state->sd, pdev);
864 platform_set_drvdata(pdev, &state->sd);
865 memcpy(state->events, s5pcsis_events, sizeof(state->events));
874 dev_info(&pdev->dev, "lanes: %d, hs_settle: %d, wclk: %d, freq: %u\n",
875 state->num_lanes, state->hs_settle, state->wclk_ext,
876 state->clk_frequency);
880 media_entity_cleanup(&state->sd.entity);
882 clk_disable(state->clock[CSIS_CLK_MUX]);
884 s5pcsis_clk_put(state);
891 struct csis_state *state = sd_to_csis_state(sd);
895 __func__, state->flags);
897 mutex_lock(&state->lock);
898 if (state->flags & ST_POWERED) {
899 s5pcsis_stop_stream(state);
900 ret = phy_power_off(state->phy);
904 state->supplies);
907 clk_disable(state->clock[CSIS_CLK_GATE]);
908 state->flags &= ~ST_POWERED;
910 state->flags |= ST_SUSPENDED;
913 mutex_unlock(&state->lock);
914 return ret ? -EAGAIN : 0;
920 struct csis_state *state = sd_to_csis_state(sd);
924 __func__, state->flags);
926 mutex_lock(&state->lock);
927 if (!runtime && !(state->flags & ST_SUSPENDED))
930 if (!(state->flags & ST_POWERED)) {
932 state->supplies);
935 ret = phy_power_on(state->phy);
937 state->flags |= ST_POWERED;
940 state->supplies);
943 ret = clk_enable(state->clock[CSIS_CLK_GATE]);
945 phy_power_off(state->phy);
947 state->supplies);
951 if (state->flags & ST_STREAMING)
952 s5pcsis_start_stream(state);
954 state->flags &= ~ST_SUSPENDED;
956 mutex_unlock(&state->lock);
957 return ret ? -EAGAIN : 0;
987 struct csis_state *state = sd_to_csis_state(sd);
989 pm_runtime_disable(&pdev->dev);
990 s5pcsis_pm_suspend(&pdev->dev, true);
991 clk_disable(state->clock[CSIS_CLK_MUX]);
992 pm_runtime_set_suspended(&pdev->dev);
993 s5pcsis_clk_put(state);
995 media_entity_cleanup(&state->sd.entity);
1014 .compatible = "samsung,s5pv210-csis",
1017 .compatible = "samsung,exynos4210-csis",
1020 .compatible = "samsung,exynos5250-csis",
1040 MODULE_DESCRIPTION("Samsung S5P/EXYNOS SoC MIPI-CSI2 receiver driver");