1 // SPDX-License-Identifier: GPL-2.0+
3 * vsp1_lif.c -- R-Car VSP1 LCD Controller Interface
5 * Copyright (C) 2013-2014 Renesas Electronics Corporation
7 * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
10 #include <linux/device.h>
11 #include <linux/gfp.h>
13 #include <media/v4l2-subdev.h>
19 #define LIF_MIN_SIZE 2U
20 #define LIF_MAX_SIZE 8190U
22 /* -----------------------------------------------------------------------------
26 static inline void vsp1_lif_write(struct vsp1_lif
*lif
,
27 struct vsp1_dl_body
*dlb
, u32 reg
, u32 data
)
29 vsp1_dl_body_write(dlb
, reg
+ lif
->entity
.index
* VI6_LIF_OFFSET
,
33 /* -----------------------------------------------------------------------------
34 * V4L2 Subdevice Operations
37 static const unsigned int lif_codes
[] = {
38 MEDIA_BUS_FMT_ARGB8888_1X32
,
39 MEDIA_BUS_FMT_AYUV8_1X32
,
42 static int lif_enum_mbus_code(struct v4l2_subdev
*subdev
,
43 struct v4l2_subdev_pad_config
*cfg
,
44 struct v4l2_subdev_mbus_code_enum
*code
)
46 return vsp1_subdev_enum_mbus_code(subdev
, cfg
, code
, lif_codes
,
47 ARRAY_SIZE(lif_codes
));
50 static int lif_enum_frame_size(struct v4l2_subdev
*subdev
,
51 struct v4l2_subdev_pad_config
*cfg
,
52 struct v4l2_subdev_frame_size_enum
*fse
)
54 return vsp1_subdev_enum_frame_size(subdev
, cfg
, fse
, LIF_MIN_SIZE
,
55 LIF_MIN_SIZE
, LIF_MAX_SIZE
,
59 static int lif_set_format(struct v4l2_subdev
*subdev
,
60 struct v4l2_subdev_pad_config
*cfg
,
61 struct v4l2_subdev_format
*fmt
)
63 return vsp1_subdev_set_pad_format(subdev
, cfg
, fmt
, lif_codes
,
64 ARRAY_SIZE(lif_codes
),
65 LIF_MIN_SIZE
, LIF_MIN_SIZE
,
66 LIF_MAX_SIZE
, LIF_MAX_SIZE
);
69 static const struct v4l2_subdev_pad_ops lif_pad_ops
= {
70 .init_cfg
= vsp1_entity_init_cfg
,
71 .enum_mbus_code
= lif_enum_mbus_code
,
72 .enum_frame_size
= lif_enum_frame_size
,
73 .get_fmt
= vsp1_subdev_get_pad_format
,
74 .set_fmt
= lif_set_format
,
77 static const struct v4l2_subdev_ops lif_ops
= {
81 /* -----------------------------------------------------------------------------
82 * VSP1 Entity Operations
85 static void lif_configure_stream(struct vsp1_entity
*entity
,
86 struct vsp1_pipeline
*pipe
,
87 struct vsp1_dl_body
*dlb
)
89 const struct v4l2_mbus_framefmt
*format
;
90 struct vsp1_lif
*lif
= to_lif(&entity
->subdev
);
91 unsigned int hbth
= 1300;
92 unsigned int obth
= 400;
93 unsigned int lbth
= 200;
95 format
= vsp1_entity_get_pad_format(&lif
->entity
, lif
->entity
.config
,
98 obth
= min(obth
, (format
->width
+ 1) / 2 * format
->height
- 4);
100 vsp1_lif_write(lif
, dlb
, VI6_LIF_CSBTH
,
101 (hbth
<< VI6_LIF_CSBTH_HBTH_SHIFT
) |
102 (lbth
<< VI6_LIF_CSBTH_LBTH_SHIFT
));
104 vsp1_lif_write(lif
, dlb
, VI6_LIF_CTRL
,
105 (obth
<< VI6_LIF_CTRL_OBTH_SHIFT
) |
106 (format
->code
== 0 ? VI6_LIF_CTRL_CFMT
: 0) |
107 VI6_LIF_CTRL_REQSEL
| VI6_LIF_CTRL_LIF_EN
);
110 * On R-Car V3M the LIF0 buffer attribute register has to be set to a
111 * non-default value to guarantee proper operation (otherwise artifacts
112 * may appear on the output). The value required by the manual is not
113 * explained but is likely a buffer size or threshold.
115 if ((entity
->vsp1
->version
& VI6_IP_VERSION_MASK
) ==
116 (VI6_IP_VERSION_MODEL_VSPD_V3
| VI6_IP_VERSION_SOC_V3M
))
117 vsp1_lif_write(lif
, dlb
, VI6_LIF_LBA
,
119 (1536 << VI6_LIF_LBA_LBA1_SHIFT
));
122 static const struct vsp1_entity_operations lif_entity_ops
= {
123 .configure_stream
= lif_configure_stream
,
126 /* -----------------------------------------------------------------------------
127 * Initialization and Cleanup
130 struct vsp1_lif
*vsp1_lif_create(struct vsp1_device
*vsp1
, unsigned int index
)
132 struct vsp1_lif
*lif
;
135 lif
= devm_kzalloc(vsp1
->dev
, sizeof(*lif
), GFP_KERNEL
);
137 return ERR_PTR(-ENOMEM
);
139 lif
->entity
.ops
= &lif_entity_ops
;
140 lif
->entity
.type
= VSP1_ENTITY_LIF
;
141 lif
->entity
.index
= index
;
144 * The LIF is never exposed to userspace, but media entity registration
145 * requires a function to be set. Use PROC_VIDEO_PIXEL_FORMATTER just to
146 * avoid triggering a WARN_ON(), the value won't be seen anywhere.
148 ret
= vsp1_entity_init(vsp1
, &lif
->entity
, "lif", 2, &lif_ops
,
149 MEDIA_ENT_F_PROC_VIDEO_PIXEL_FORMATTER
);