1*41ec0267Sriastradh /* $NetBSD: drm_mipi_dsi.c,v 1.3 2021/12/18 23:44:57 riastradh Exp $ */
2efa246c0Sriastradh
39d20d926Sriastradh /*
49d20d926Sriastradh * MIPI DSI Bus
59d20d926Sriastradh *
69d20d926Sriastradh * Copyright (C) 2012-2013, Samsung Electronics, Co., Ltd.
79d20d926Sriastradh * Andrzej Hajda <a.hajda@samsung.com>
89d20d926Sriastradh *
99d20d926Sriastradh * Permission is hereby granted, free of charge, to any person obtaining a
109d20d926Sriastradh * copy of this software and associated documentation files (the
119d20d926Sriastradh * "Software"), to deal in the Software without restriction, including
129d20d926Sriastradh * without limitation the rights to use, copy, modify, merge, publish,
139d20d926Sriastradh * distribute, sub license, and/or sell copies of the Software, and to
149d20d926Sriastradh * permit persons to whom the Software is furnished to do so, subject to
159d20d926Sriastradh * the following conditions:
169d20d926Sriastradh *
179d20d926Sriastradh * The above copyright notice and this permission notice (including the
189d20d926Sriastradh * next paragraph) shall be included in all copies or substantial portions
199d20d926Sriastradh * of the Software.
209d20d926Sriastradh *
219d20d926Sriastradh * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
229d20d926Sriastradh * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
239d20d926Sriastradh * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
249d20d926Sriastradh * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
259d20d926Sriastradh * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
269d20d926Sriastradh * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
279d20d926Sriastradh * USE OR OTHER DEALINGS IN THE SOFTWARE.
289d20d926Sriastradh */
299d20d926Sriastradh
30efa246c0Sriastradh #include <sys/cdefs.h>
31*41ec0267Sriastradh __KERNEL_RCSID(0, "$NetBSD: drm_mipi_dsi.c,v 1.3 2021/12/18 23:44:57 riastradh Exp $");
32efa246c0Sriastradh
339d20d926Sriastradh #include <drm/drm_mipi_dsi.h>
349d20d926Sriastradh
359d20d926Sriastradh #include <linux/device.h>
369d20d926Sriastradh #include <linux/module.h>
379d20d926Sriastradh #include <linux/of_device.h>
389d20d926Sriastradh #include <linux/pm_runtime.h>
399d20d926Sriastradh #include <linux/slab.h>
409d20d926Sriastradh
41*41ec0267Sriastradh #include <drm/drm_dsc.h>
429d20d926Sriastradh #include <video/mipi_display.h>
439d20d926Sriastradh
44efa246c0Sriastradh /**
45efa246c0Sriastradh * DOC: dsi helpers
46efa246c0Sriastradh *
47efa246c0Sriastradh * These functions contain some common logic and helpers to deal with MIPI DSI
48efa246c0Sriastradh * peripherals.
49efa246c0Sriastradh *
50efa246c0Sriastradh * Helpers are provided for a number of standard MIPI DSI command as well as a
51efa246c0Sriastradh * subset of the MIPI DCS command set.
52efa246c0Sriastradh */
53efa246c0Sriastradh
mipi_dsi_device_match(struct device * dev,struct device_driver * drv)549d20d926Sriastradh static int mipi_dsi_device_match(struct device *dev, struct device_driver *drv)
559d20d926Sriastradh {
56*41ec0267Sriastradh struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev);
57*41ec0267Sriastradh
58*41ec0267Sriastradh /* attempt OF style match */
59*41ec0267Sriastradh if (of_driver_match_device(dev, drv))
60*41ec0267Sriastradh return 1;
61*41ec0267Sriastradh
62*41ec0267Sriastradh /* compare DSI device and driver names */
63*41ec0267Sriastradh if (!strcmp(dsi->name, drv->name))
64*41ec0267Sriastradh return 1;
65*41ec0267Sriastradh
66*41ec0267Sriastradh return 0;
67*41ec0267Sriastradh }
68*41ec0267Sriastradh
mipi_dsi_uevent(struct device * dev,struct kobj_uevent_env * env)69*41ec0267Sriastradh static int mipi_dsi_uevent(struct device *dev, struct kobj_uevent_env *env)
70*41ec0267Sriastradh {
71*41ec0267Sriastradh struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev);
72*41ec0267Sriastradh int err;
73*41ec0267Sriastradh
74*41ec0267Sriastradh err = of_device_uevent_modalias(dev, env);
75*41ec0267Sriastradh if (err != -ENODEV)
76*41ec0267Sriastradh return err;
77*41ec0267Sriastradh
78*41ec0267Sriastradh add_uevent_var(env, "MODALIAS=%s%s", MIPI_DSI_MODULE_PREFIX,
79*41ec0267Sriastradh dsi->name);
80*41ec0267Sriastradh
81*41ec0267Sriastradh return 0;
829d20d926Sriastradh }
839d20d926Sriastradh
849d20d926Sriastradh static const struct dev_pm_ops mipi_dsi_device_pm_ops = {
859d20d926Sriastradh .runtime_suspend = pm_generic_runtime_suspend,
869d20d926Sriastradh .runtime_resume = pm_generic_runtime_resume,
879d20d926Sriastradh .suspend = pm_generic_suspend,
889d20d926Sriastradh .resume = pm_generic_resume,
899d20d926Sriastradh .freeze = pm_generic_freeze,
909d20d926Sriastradh .thaw = pm_generic_thaw,
919d20d926Sriastradh .poweroff = pm_generic_poweroff,
929d20d926Sriastradh .restore = pm_generic_restore,
939d20d926Sriastradh };
949d20d926Sriastradh
959d20d926Sriastradh static struct bus_type mipi_dsi_bus_type = {
969d20d926Sriastradh .name = "mipi-dsi",
979d20d926Sriastradh .match = mipi_dsi_device_match,
98*41ec0267Sriastradh .uevent = mipi_dsi_uevent,
999d20d926Sriastradh .pm = &mipi_dsi_device_pm_ops,
1009d20d926Sriastradh };
1019d20d926Sriastradh
102efa246c0Sriastradh /**
103efa246c0Sriastradh * of_find_mipi_dsi_device_by_node() - find the MIPI DSI device matching a
104efa246c0Sriastradh * device tree node
105efa246c0Sriastradh * @np: device tree node
106efa246c0Sriastradh *
107efa246c0Sriastradh * Return: A pointer to the MIPI DSI device corresponding to @np or NULL if no
108efa246c0Sriastradh * such device exists (or has not been registered yet).
109efa246c0Sriastradh */
of_find_mipi_dsi_device_by_node(struct device_node * np)110efa246c0Sriastradh struct mipi_dsi_device *of_find_mipi_dsi_device_by_node(struct device_node *np)
111efa246c0Sriastradh {
112efa246c0Sriastradh struct device *dev;
113efa246c0Sriastradh
114*41ec0267Sriastradh dev = bus_find_device_by_of_node(&mipi_dsi_bus_type, np);
115efa246c0Sriastradh
116efa246c0Sriastradh return dev ? to_mipi_dsi_device(dev) : NULL;
117efa246c0Sriastradh }
118efa246c0Sriastradh EXPORT_SYMBOL(of_find_mipi_dsi_device_by_node);
119efa246c0Sriastradh
mipi_dsi_dev_release(struct device * dev)1209d20d926Sriastradh static void mipi_dsi_dev_release(struct device *dev)
1219d20d926Sriastradh {
1229d20d926Sriastradh struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev);
1239d20d926Sriastradh
1249d20d926Sriastradh of_node_put(dev->of_node);
1259d20d926Sriastradh kfree(dsi);
1269d20d926Sriastradh }
1279d20d926Sriastradh
1289d20d926Sriastradh static const struct device_type mipi_dsi_device_type = {
1299d20d926Sriastradh .release = mipi_dsi_dev_release,
1309d20d926Sriastradh };
1319d20d926Sriastradh
mipi_dsi_device_alloc(struct mipi_dsi_host * host)1329d20d926Sriastradh static struct mipi_dsi_device *mipi_dsi_device_alloc(struct mipi_dsi_host *host)
1339d20d926Sriastradh {
1349d20d926Sriastradh struct mipi_dsi_device *dsi;
1359d20d926Sriastradh
1369d20d926Sriastradh dsi = kzalloc(sizeof(*dsi), GFP_KERNEL);
1379d20d926Sriastradh if (!dsi)
1389d20d926Sriastradh return ERR_PTR(-ENOMEM);
1399d20d926Sriastradh
1409d20d926Sriastradh dsi->host = host;
1419d20d926Sriastradh dsi->dev.bus = &mipi_dsi_bus_type;
1429d20d926Sriastradh dsi->dev.parent = host->dev;
1439d20d926Sriastradh dsi->dev.type = &mipi_dsi_device_type;
1449d20d926Sriastradh
1459d20d926Sriastradh device_initialize(&dsi->dev);
1469d20d926Sriastradh
1479d20d926Sriastradh return dsi;
1489d20d926Sriastradh }
1499d20d926Sriastradh
mipi_dsi_device_add(struct mipi_dsi_device * dsi)1509d20d926Sriastradh static int mipi_dsi_device_add(struct mipi_dsi_device *dsi)
1519d20d926Sriastradh {
1529d20d926Sriastradh struct mipi_dsi_host *host = dsi->host;
1539d20d926Sriastradh
1549d20d926Sriastradh dev_set_name(&dsi->dev, "%s.%d", dev_name(host->dev), dsi->channel);
1559d20d926Sriastradh
1569d20d926Sriastradh return device_add(&dsi->dev);
1579d20d926Sriastradh }
1589d20d926Sriastradh
159*41ec0267Sriastradh #if IS_ENABLED(CONFIG_OF)
1609d20d926Sriastradh static struct mipi_dsi_device *
of_mipi_dsi_device_add(struct mipi_dsi_host * host,struct device_node * node)1619d20d926Sriastradh of_mipi_dsi_device_add(struct mipi_dsi_host *host, struct device_node *node)
1629d20d926Sriastradh {
163*41ec0267Sriastradh struct device *dev = host->dev;
164*41ec0267Sriastradh struct mipi_dsi_device_info info = { };
165*41ec0267Sriastradh int ret;
166*41ec0267Sriastradh u32 reg;
167*41ec0267Sriastradh
168*41ec0267Sriastradh if (of_modalias_node(node, info.type, sizeof(info.type)) < 0) {
169*41ec0267Sriastradh dev_err(dev, "modalias failure on %pOF\n", node);
170*41ec0267Sriastradh return ERR_PTR(-EINVAL);
171*41ec0267Sriastradh }
172*41ec0267Sriastradh
173*41ec0267Sriastradh ret = of_property_read_u32(node, "reg", ®);
174*41ec0267Sriastradh if (ret) {
175*41ec0267Sriastradh dev_err(dev, "device node %pOF has no valid reg property: %d\n",
176*41ec0267Sriastradh node, ret);
177*41ec0267Sriastradh return ERR_PTR(-EINVAL);
178*41ec0267Sriastradh }
179*41ec0267Sriastradh
180*41ec0267Sriastradh info.channel = reg;
181*41ec0267Sriastradh info.node = of_node_get(node);
182*41ec0267Sriastradh
183*41ec0267Sriastradh return mipi_dsi_device_register_full(host, &info);
184*41ec0267Sriastradh }
185*41ec0267Sriastradh #else
186*41ec0267Sriastradh static struct mipi_dsi_device *
of_mipi_dsi_device_add(struct mipi_dsi_host * host,struct device_node * node)187*41ec0267Sriastradh of_mipi_dsi_device_add(struct mipi_dsi_host *host, struct device_node *node)
188*41ec0267Sriastradh {
189*41ec0267Sriastradh return ERR_PTR(-ENODEV);
190*41ec0267Sriastradh }
191*41ec0267Sriastradh #endif
192*41ec0267Sriastradh
193*41ec0267Sriastradh /**
194*41ec0267Sriastradh * mipi_dsi_device_register_full - create a MIPI DSI device
195*41ec0267Sriastradh * @host: DSI host to which this device is connected
196*41ec0267Sriastradh * @info: pointer to template containing DSI device information
197*41ec0267Sriastradh *
198*41ec0267Sriastradh * Create a MIPI DSI device by using the device information provided by
199*41ec0267Sriastradh * mipi_dsi_device_info template
200*41ec0267Sriastradh *
201*41ec0267Sriastradh * Returns:
202*41ec0267Sriastradh * A pointer to the newly created MIPI DSI device, or, a pointer encoded
203*41ec0267Sriastradh * with an error
204*41ec0267Sriastradh */
205*41ec0267Sriastradh struct mipi_dsi_device *
mipi_dsi_device_register_full(struct mipi_dsi_host * host,const struct mipi_dsi_device_info * info)206*41ec0267Sriastradh mipi_dsi_device_register_full(struct mipi_dsi_host *host,
207*41ec0267Sriastradh const struct mipi_dsi_device_info *info)
208*41ec0267Sriastradh {
2099d20d926Sriastradh struct mipi_dsi_device *dsi;
2109d20d926Sriastradh struct device *dev = host->dev;
2119d20d926Sriastradh int ret;
2129d20d926Sriastradh
213*41ec0267Sriastradh if (!info) {
214*41ec0267Sriastradh dev_err(dev, "invalid mipi_dsi_device_info pointer\n");
2159d20d926Sriastradh return ERR_PTR(-EINVAL);
2169d20d926Sriastradh }
2179d20d926Sriastradh
218*41ec0267Sriastradh if (info->channel > 3) {
219*41ec0267Sriastradh dev_err(dev, "invalid virtual channel: %u\n", info->channel);
2209d20d926Sriastradh return ERR_PTR(-EINVAL);
2219d20d926Sriastradh }
2229d20d926Sriastradh
2239d20d926Sriastradh dsi = mipi_dsi_device_alloc(host);
2249d20d926Sriastradh if (IS_ERR(dsi)) {
225*41ec0267Sriastradh dev_err(dev, "failed to allocate DSI device %ld\n",
226*41ec0267Sriastradh PTR_ERR(dsi));
2279d20d926Sriastradh return dsi;
2289d20d926Sriastradh }
2299d20d926Sriastradh
230*41ec0267Sriastradh dsi->dev.of_node = info->node;
231*41ec0267Sriastradh dsi->channel = info->channel;
232*41ec0267Sriastradh strlcpy(dsi->name, info->type, sizeof(dsi->name));
2339d20d926Sriastradh
2349d20d926Sriastradh ret = mipi_dsi_device_add(dsi);
2359d20d926Sriastradh if (ret) {
236*41ec0267Sriastradh dev_err(dev, "failed to add DSI device %d\n", ret);
2379d20d926Sriastradh kfree(dsi);
2389d20d926Sriastradh return ERR_PTR(ret);
2399d20d926Sriastradh }
2409d20d926Sriastradh
2419d20d926Sriastradh return dsi;
2429d20d926Sriastradh }
243*41ec0267Sriastradh EXPORT_SYMBOL(mipi_dsi_device_register_full);
244*41ec0267Sriastradh
245*41ec0267Sriastradh /**
246*41ec0267Sriastradh * mipi_dsi_device_unregister - unregister MIPI DSI device
247*41ec0267Sriastradh * @dsi: DSI peripheral device
248*41ec0267Sriastradh */
mipi_dsi_device_unregister(struct mipi_dsi_device * dsi)249*41ec0267Sriastradh void mipi_dsi_device_unregister(struct mipi_dsi_device *dsi)
250*41ec0267Sriastradh {
251*41ec0267Sriastradh device_unregister(&dsi->dev);
252*41ec0267Sriastradh }
253*41ec0267Sriastradh EXPORT_SYMBOL(mipi_dsi_device_unregister);
254*41ec0267Sriastradh
255*41ec0267Sriastradh static DEFINE_MUTEX(host_lock);
256*41ec0267Sriastradh static LIST_HEAD(host_list);
257*41ec0267Sriastradh
258*41ec0267Sriastradh /**
259*41ec0267Sriastradh * of_find_mipi_dsi_host_by_node() - find the MIPI DSI host matching a
260*41ec0267Sriastradh * device tree node
261*41ec0267Sriastradh * @node: device tree node
262*41ec0267Sriastradh *
263*41ec0267Sriastradh * Returns:
264*41ec0267Sriastradh * A pointer to the MIPI DSI host corresponding to @node or NULL if no
265*41ec0267Sriastradh * such device exists (or has not been registered yet).
266*41ec0267Sriastradh */
of_find_mipi_dsi_host_by_node(struct device_node * node)267*41ec0267Sriastradh struct mipi_dsi_host *of_find_mipi_dsi_host_by_node(struct device_node *node)
268*41ec0267Sriastradh {
269*41ec0267Sriastradh struct mipi_dsi_host *host;
270*41ec0267Sriastradh
271*41ec0267Sriastradh mutex_lock(&host_lock);
272*41ec0267Sriastradh
273*41ec0267Sriastradh list_for_each_entry(host, &host_list, list) {
274*41ec0267Sriastradh if (host->dev->of_node == node) {
275*41ec0267Sriastradh mutex_unlock(&host_lock);
276*41ec0267Sriastradh return host;
277*41ec0267Sriastradh }
278*41ec0267Sriastradh }
279*41ec0267Sriastradh
280*41ec0267Sriastradh mutex_unlock(&host_lock);
281*41ec0267Sriastradh
282*41ec0267Sriastradh return NULL;
283*41ec0267Sriastradh }
284*41ec0267Sriastradh EXPORT_SYMBOL(of_find_mipi_dsi_host_by_node);
2859d20d926Sriastradh
mipi_dsi_host_register(struct mipi_dsi_host * host)2869d20d926Sriastradh int mipi_dsi_host_register(struct mipi_dsi_host *host)
2879d20d926Sriastradh {
2889d20d926Sriastradh struct device_node *node;
2899d20d926Sriastradh
2909d20d926Sriastradh for_each_available_child_of_node(host->dev->of_node, node) {
2919d20d926Sriastradh /* skip nodes without reg property */
2929d20d926Sriastradh if (!of_find_property(node, "reg", NULL))
2939d20d926Sriastradh continue;
2949d20d926Sriastradh of_mipi_dsi_device_add(host, node);
2959d20d926Sriastradh }
2969d20d926Sriastradh
297*41ec0267Sriastradh mutex_lock(&host_lock);
298*41ec0267Sriastradh list_add_tail(&host->list, &host_list);
299*41ec0267Sriastradh mutex_unlock(&host_lock);
300*41ec0267Sriastradh
3019d20d926Sriastradh return 0;
3029d20d926Sriastradh }
3039d20d926Sriastradh EXPORT_SYMBOL(mipi_dsi_host_register);
3049d20d926Sriastradh
mipi_dsi_remove_device_fn(struct device * dev,void * priv)3059d20d926Sriastradh static int mipi_dsi_remove_device_fn(struct device *dev, void *priv)
3069d20d926Sriastradh {
3079d20d926Sriastradh struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev);
3089d20d926Sriastradh
309*41ec0267Sriastradh mipi_dsi_device_unregister(dsi);
3109d20d926Sriastradh
3119d20d926Sriastradh return 0;
3129d20d926Sriastradh }
3139d20d926Sriastradh
mipi_dsi_host_unregister(struct mipi_dsi_host * host)3149d20d926Sriastradh void mipi_dsi_host_unregister(struct mipi_dsi_host *host)
3159d20d926Sriastradh {
3169d20d926Sriastradh device_for_each_child(host->dev, NULL, mipi_dsi_remove_device_fn);
317*41ec0267Sriastradh
318*41ec0267Sriastradh mutex_lock(&host_lock);
319*41ec0267Sriastradh list_del_init(&host->list);
320*41ec0267Sriastradh mutex_unlock(&host_lock);
3219d20d926Sriastradh }
3229d20d926Sriastradh EXPORT_SYMBOL(mipi_dsi_host_unregister);
3239d20d926Sriastradh
3249d20d926Sriastradh /**
3259d20d926Sriastradh * mipi_dsi_attach - attach a DSI device to its DSI host
3269d20d926Sriastradh * @dsi: DSI peripheral
3279d20d926Sriastradh */
mipi_dsi_attach(struct mipi_dsi_device * dsi)3289d20d926Sriastradh int mipi_dsi_attach(struct mipi_dsi_device *dsi)
3299d20d926Sriastradh {
3309d20d926Sriastradh const struct mipi_dsi_host_ops *ops = dsi->host->ops;
3319d20d926Sriastradh
3329d20d926Sriastradh if (!ops || !ops->attach)
3339d20d926Sriastradh return -ENOSYS;
3349d20d926Sriastradh
3359d20d926Sriastradh return ops->attach(dsi->host, dsi);
3369d20d926Sriastradh }
3379d20d926Sriastradh EXPORT_SYMBOL(mipi_dsi_attach);
3389d20d926Sriastradh
3399d20d926Sriastradh /**
3409d20d926Sriastradh * mipi_dsi_detach - detach a DSI device from its DSI host
3419d20d926Sriastradh * @dsi: DSI peripheral
3429d20d926Sriastradh */
mipi_dsi_detach(struct mipi_dsi_device * dsi)3439d20d926Sriastradh int mipi_dsi_detach(struct mipi_dsi_device *dsi)
3449d20d926Sriastradh {
3459d20d926Sriastradh const struct mipi_dsi_host_ops *ops = dsi->host->ops;
3469d20d926Sriastradh
3479d20d926Sriastradh if (!ops || !ops->detach)
3489d20d926Sriastradh return -ENOSYS;
3499d20d926Sriastradh
3509d20d926Sriastradh return ops->detach(dsi->host, dsi);
3519d20d926Sriastradh }
3529d20d926Sriastradh EXPORT_SYMBOL(mipi_dsi_detach);
3539d20d926Sriastradh
mipi_dsi_device_transfer(struct mipi_dsi_device * dsi,struct mipi_dsi_msg * msg)354efa246c0Sriastradh static ssize_t mipi_dsi_device_transfer(struct mipi_dsi_device *dsi,
355efa246c0Sriastradh struct mipi_dsi_msg *msg)
3569d20d926Sriastradh {
3579d20d926Sriastradh const struct mipi_dsi_host_ops *ops = dsi->host->ops;
3589d20d926Sriastradh
3599d20d926Sriastradh if (!ops || !ops->transfer)
3609d20d926Sriastradh return -ENOSYS;
3619d20d926Sriastradh
362efa246c0Sriastradh if (dsi->mode_flags & MIPI_DSI_MODE_LPM)
363efa246c0Sriastradh msg->flags |= MIPI_DSI_MSG_USE_LPM;
364efa246c0Sriastradh
365efa246c0Sriastradh return ops->transfer(dsi->host, msg);
366efa246c0Sriastradh }
367efa246c0Sriastradh
368efa246c0Sriastradh /**
369efa246c0Sriastradh * mipi_dsi_packet_format_is_short - check if a packet is of the short format
370efa246c0Sriastradh * @type: MIPI DSI data type of the packet
371efa246c0Sriastradh *
372efa246c0Sriastradh * Return: true if the packet for the given data type is a short packet, false
373efa246c0Sriastradh * otherwise.
374efa246c0Sriastradh */
mipi_dsi_packet_format_is_short(u8 type)375efa246c0Sriastradh bool mipi_dsi_packet_format_is_short(u8 type)
376efa246c0Sriastradh {
377efa246c0Sriastradh switch (type) {
378efa246c0Sriastradh case MIPI_DSI_V_SYNC_START:
379efa246c0Sriastradh case MIPI_DSI_V_SYNC_END:
380efa246c0Sriastradh case MIPI_DSI_H_SYNC_START:
381efa246c0Sriastradh case MIPI_DSI_H_SYNC_END:
382*41ec0267Sriastradh case MIPI_DSI_COMPRESSION_MODE:
383efa246c0Sriastradh case MIPI_DSI_END_OF_TRANSMISSION:
384efa246c0Sriastradh case MIPI_DSI_COLOR_MODE_OFF:
385efa246c0Sriastradh case MIPI_DSI_COLOR_MODE_ON:
386efa246c0Sriastradh case MIPI_DSI_SHUTDOWN_PERIPHERAL:
387efa246c0Sriastradh case MIPI_DSI_TURN_ON_PERIPHERAL:
388efa246c0Sriastradh case MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM:
389efa246c0Sriastradh case MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM:
390efa246c0Sriastradh case MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM:
391efa246c0Sriastradh case MIPI_DSI_GENERIC_READ_REQUEST_0_PARAM:
392efa246c0Sriastradh case MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM:
393efa246c0Sriastradh case MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM:
394efa246c0Sriastradh case MIPI_DSI_DCS_SHORT_WRITE:
395efa246c0Sriastradh case MIPI_DSI_DCS_SHORT_WRITE_PARAM:
396efa246c0Sriastradh case MIPI_DSI_DCS_READ:
397*41ec0267Sriastradh case MIPI_DSI_EXECUTE_QUEUE:
398efa246c0Sriastradh case MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE:
399efa246c0Sriastradh return true;
400efa246c0Sriastradh }
401efa246c0Sriastradh
402efa246c0Sriastradh return false;
403efa246c0Sriastradh }
404efa246c0Sriastradh EXPORT_SYMBOL(mipi_dsi_packet_format_is_short);
405efa246c0Sriastradh
406efa246c0Sriastradh /**
407efa246c0Sriastradh * mipi_dsi_packet_format_is_long - check if a packet is of the long format
408efa246c0Sriastradh * @type: MIPI DSI data type of the packet
409efa246c0Sriastradh *
410efa246c0Sriastradh * Return: true if the packet for the given data type is a long packet, false
411efa246c0Sriastradh * otherwise.
412efa246c0Sriastradh */
mipi_dsi_packet_format_is_long(u8 type)413efa246c0Sriastradh bool mipi_dsi_packet_format_is_long(u8 type)
414efa246c0Sriastradh {
415efa246c0Sriastradh switch (type) {
416efa246c0Sriastradh case MIPI_DSI_NULL_PACKET:
417efa246c0Sriastradh case MIPI_DSI_BLANKING_PACKET:
418efa246c0Sriastradh case MIPI_DSI_GENERIC_LONG_WRITE:
419efa246c0Sriastradh case MIPI_DSI_DCS_LONG_WRITE:
420*41ec0267Sriastradh case MIPI_DSI_PICTURE_PARAMETER_SET:
421*41ec0267Sriastradh case MIPI_DSI_COMPRESSED_PIXEL_STREAM:
422efa246c0Sriastradh case MIPI_DSI_LOOSELY_PACKED_PIXEL_STREAM_YCBCR20:
423efa246c0Sriastradh case MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR24:
424efa246c0Sriastradh case MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR16:
425efa246c0Sriastradh case MIPI_DSI_PACKED_PIXEL_STREAM_30:
426efa246c0Sriastradh case MIPI_DSI_PACKED_PIXEL_STREAM_36:
427efa246c0Sriastradh case MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR12:
428efa246c0Sriastradh case MIPI_DSI_PACKED_PIXEL_STREAM_16:
429efa246c0Sriastradh case MIPI_DSI_PACKED_PIXEL_STREAM_18:
430efa246c0Sriastradh case MIPI_DSI_PIXEL_STREAM_3BYTE_18:
431efa246c0Sriastradh case MIPI_DSI_PACKED_PIXEL_STREAM_24:
432efa246c0Sriastradh return true;
433efa246c0Sriastradh }
434efa246c0Sriastradh
435efa246c0Sriastradh return false;
436efa246c0Sriastradh }
437efa246c0Sriastradh EXPORT_SYMBOL(mipi_dsi_packet_format_is_long);
438efa246c0Sriastradh
439efa246c0Sriastradh /**
440efa246c0Sriastradh * mipi_dsi_create_packet - create a packet from a message according to the
441efa246c0Sriastradh * DSI protocol
442efa246c0Sriastradh * @packet: pointer to a DSI packet structure
443efa246c0Sriastradh * @msg: message to translate into a packet
444efa246c0Sriastradh *
445efa246c0Sriastradh * Return: 0 on success or a negative error code on failure.
446efa246c0Sriastradh */
mipi_dsi_create_packet(struct mipi_dsi_packet * packet,const struct mipi_dsi_msg * msg)447efa246c0Sriastradh int mipi_dsi_create_packet(struct mipi_dsi_packet *packet,
448efa246c0Sriastradh const struct mipi_dsi_msg *msg)
449efa246c0Sriastradh {
450efa246c0Sriastradh if (!packet || !msg)
451efa246c0Sriastradh return -EINVAL;
452efa246c0Sriastradh
453efa246c0Sriastradh /* do some minimum sanity checking */
454efa246c0Sriastradh if (!mipi_dsi_packet_format_is_short(msg->type) &&
455efa246c0Sriastradh !mipi_dsi_packet_format_is_long(msg->type))
456efa246c0Sriastradh return -EINVAL;
457efa246c0Sriastradh
458efa246c0Sriastradh if (msg->channel > 3)
459efa246c0Sriastradh return -EINVAL;
460efa246c0Sriastradh
461efa246c0Sriastradh memset(packet, 0, sizeof(*packet));
462efa246c0Sriastradh packet->header[0] = ((msg->channel & 0x3) << 6) | (msg->type & 0x3f);
463efa246c0Sriastradh
464efa246c0Sriastradh /* TODO: compute ECC if hardware support is not available */
465efa246c0Sriastradh
466efa246c0Sriastradh /*
467efa246c0Sriastradh * Long write packets contain the word count in header bytes 1 and 2.
468efa246c0Sriastradh * The payload follows the header and is word count bytes long.
469efa246c0Sriastradh *
470efa246c0Sriastradh * Short write packets encode up to two parameters in header bytes 1
471efa246c0Sriastradh * and 2.
472efa246c0Sriastradh */
473efa246c0Sriastradh if (mipi_dsi_packet_format_is_long(msg->type)) {
474efa246c0Sriastradh packet->header[1] = (msg->tx_len >> 0) & 0xff;
475efa246c0Sriastradh packet->header[2] = (msg->tx_len >> 8) & 0xff;
476efa246c0Sriastradh
477efa246c0Sriastradh packet->payload_length = msg->tx_len;
478efa246c0Sriastradh packet->payload = msg->tx_buf;
479efa246c0Sriastradh } else {
480efa246c0Sriastradh const u8 *tx = msg->tx_buf;
481efa246c0Sriastradh
482efa246c0Sriastradh packet->header[1] = (msg->tx_len > 0) ? tx[0] : 0;
483efa246c0Sriastradh packet->header[2] = (msg->tx_len > 1) ? tx[1] : 0;
484efa246c0Sriastradh }
485efa246c0Sriastradh
486efa246c0Sriastradh packet->size = sizeof(packet->header) + packet->payload_length;
487efa246c0Sriastradh
488efa246c0Sriastradh return 0;
489efa246c0Sriastradh }
490efa246c0Sriastradh EXPORT_SYMBOL(mipi_dsi_create_packet);
491efa246c0Sriastradh
492*41ec0267Sriastradh /**
493*41ec0267Sriastradh * mipi_dsi_shutdown_peripheral() - sends a Shutdown Peripheral command
494*41ec0267Sriastradh * @dsi: DSI peripheral device
495*41ec0267Sriastradh *
496*41ec0267Sriastradh * Return: 0 on success or a negative error code on failure.
497*41ec0267Sriastradh */
mipi_dsi_shutdown_peripheral(struct mipi_dsi_device * dsi)498*41ec0267Sriastradh int mipi_dsi_shutdown_peripheral(struct mipi_dsi_device *dsi)
499*41ec0267Sriastradh {
500*41ec0267Sriastradh struct mipi_dsi_msg msg = {
501*41ec0267Sriastradh .channel = dsi->channel,
502*41ec0267Sriastradh .type = MIPI_DSI_SHUTDOWN_PERIPHERAL,
503*41ec0267Sriastradh .tx_buf = (u8 [2]) { 0, 0 },
504*41ec0267Sriastradh .tx_len = 2,
505*41ec0267Sriastradh };
506*41ec0267Sriastradh int ret = mipi_dsi_device_transfer(dsi, &msg);
507*41ec0267Sriastradh
508*41ec0267Sriastradh return (ret < 0) ? ret : 0;
509*41ec0267Sriastradh }
510*41ec0267Sriastradh EXPORT_SYMBOL(mipi_dsi_shutdown_peripheral);
511*41ec0267Sriastradh
512*41ec0267Sriastradh /**
513*41ec0267Sriastradh * mipi_dsi_turn_on_peripheral() - sends a Turn On Peripheral command
514*41ec0267Sriastradh * @dsi: DSI peripheral device
515*41ec0267Sriastradh *
516*41ec0267Sriastradh * Return: 0 on success or a negative error code on failure.
517*41ec0267Sriastradh */
mipi_dsi_turn_on_peripheral(struct mipi_dsi_device * dsi)518*41ec0267Sriastradh int mipi_dsi_turn_on_peripheral(struct mipi_dsi_device *dsi)
519*41ec0267Sriastradh {
520*41ec0267Sriastradh struct mipi_dsi_msg msg = {
521*41ec0267Sriastradh .channel = dsi->channel,
522*41ec0267Sriastradh .type = MIPI_DSI_TURN_ON_PERIPHERAL,
523*41ec0267Sriastradh .tx_buf = (u8 [2]) { 0, 0 },
524*41ec0267Sriastradh .tx_len = 2,
525*41ec0267Sriastradh };
526*41ec0267Sriastradh int ret = mipi_dsi_device_transfer(dsi, &msg);
527*41ec0267Sriastradh
528*41ec0267Sriastradh return (ret < 0) ? ret : 0;
529*41ec0267Sriastradh }
530*41ec0267Sriastradh EXPORT_SYMBOL(mipi_dsi_turn_on_peripheral);
531*41ec0267Sriastradh
532efa246c0Sriastradh /*
533efa246c0Sriastradh * mipi_dsi_set_maximum_return_packet_size() - specify the maximum size of the
534efa246c0Sriastradh * the payload in a long packet transmitted from the peripheral back to the
535efa246c0Sriastradh * host processor
536efa246c0Sriastradh * @dsi: DSI peripheral device
537efa246c0Sriastradh * @value: the maximum size of the payload
538efa246c0Sriastradh *
539efa246c0Sriastradh * Return: 0 on success or a negative error code on failure.
540efa246c0Sriastradh */
mipi_dsi_set_maximum_return_packet_size(struct mipi_dsi_device * dsi,u16 value)541efa246c0Sriastradh int mipi_dsi_set_maximum_return_packet_size(struct mipi_dsi_device *dsi,
542efa246c0Sriastradh u16 value)
543efa246c0Sriastradh {
544efa246c0Sriastradh u8 tx[2] = { value & 0xff, value >> 8 };
545efa246c0Sriastradh struct mipi_dsi_msg msg = {
546efa246c0Sriastradh .channel = dsi->channel,
547efa246c0Sriastradh .type = MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE,
548efa246c0Sriastradh .tx_len = sizeof(tx),
549efa246c0Sriastradh .tx_buf = tx,
550efa246c0Sriastradh };
551*41ec0267Sriastradh int ret = mipi_dsi_device_transfer(dsi, &msg);
552efa246c0Sriastradh
553*41ec0267Sriastradh return (ret < 0) ? ret : 0;
554efa246c0Sriastradh }
555efa246c0Sriastradh EXPORT_SYMBOL(mipi_dsi_set_maximum_return_packet_size);
556efa246c0Sriastradh
557efa246c0Sriastradh /**
558*41ec0267Sriastradh * mipi_dsi_compression_mode() - enable/disable DSC on the peripheral
559*41ec0267Sriastradh * @dsi: DSI peripheral device
560*41ec0267Sriastradh * @enable: Whether to enable or disable the DSC
561*41ec0267Sriastradh *
562*41ec0267Sriastradh * Enable or disable Display Stream Compression on the peripheral using the
563*41ec0267Sriastradh * default Picture Parameter Set and VESA DSC 1.1 algorithm.
564*41ec0267Sriastradh *
565*41ec0267Sriastradh * Return: 0 on success or a negative error code on failure.
566*41ec0267Sriastradh */
mipi_dsi_compression_mode(struct mipi_dsi_device * dsi,bool enable)567*41ec0267Sriastradh ssize_t mipi_dsi_compression_mode(struct mipi_dsi_device *dsi, bool enable)
568*41ec0267Sriastradh {
569*41ec0267Sriastradh /* Note: Needs updating for non-default PPS or algorithm */
570*41ec0267Sriastradh u8 tx[2] = { enable << 0, 0 };
571*41ec0267Sriastradh struct mipi_dsi_msg msg = {
572*41ec0267Sriastradh .channel = dsi->channel,
573*41ec0267Sriastradh .type = MIPI_DSI_COMPRESSION_MODE,
574*41ec0267Sriastradh .tx_len = sizeof(tx),
575*41ec0267Sriastradh .tx_buf = tx,
576*41ec0267Sriastradh };
577*41ec0267Sriastradh int ret = mipi_dsi_device_transfer(dsi, &msg);
578*41ec0267Sriastradh
579*41ec0267Sriastradh return (ret < 0) ? ret : 0;
580*41ec0267Sriastradh }
581*41ec0267Sriastradh EXPORT_SYMBOL(mipi_dsi_compression_mode);
582*41ec0267Sriastradh
583*41ec0267Sriastradh /**
584*41ec0267Sriastradh * mipi_dsi_picture_parameter_set() - transmit the DSC PPS to the peripheral
585*41ec0267Sriastradh * @dsi: DSI peripheral device
586*41ec0267Sriastradh * @pps: VESA DSC 1.1 Picture Parameter Set
587*41ec0267Sriastradh *
588*41ec0267Sriastradh * Transmit the VESA DSC 1.1 Picture Parameter Set to the peripheral.
589*41ec0267Sriastradh *
590*41ec0267Sriastradh * Return: 0 on success or a negative error code on failure.
591*41ec0267Sriastradh */
mipi_dsi_picture_parameter_set(struct mipi_dsi_device * dsi,const struct drm_dsc_picture_parameter_set * pps)592*41ec0267Sriastradh ssize_t mipi_dsi_picture_parameter_set(struct mipi_dsi_device *dsi,
593*41ec0267Sriastradh const struct drm_dsc_picture_parameter_set *pps)
594*41ec0267Sriastradh {
595*41ec0267Sriastradh struct mipi_dsi_msg msg = {
596*41ec0267Sriastradh .channel = dsi->channel,
597*41ec0267Sriastradh .type = MIPI_DSI_PICTURE_PARAMETER_SET,
598*41ec0267Sriastradh .tx_len = sizeof(*pps),
599*41ec0267Sriastradh .tx_buf = pps,
600*41ec0267Sriastradh };
601*41ec0267Sriastradh int ret = mipi_dsi_device_transfer(dsi, &msg);
602*41ec0267Sriastradh
603*41ec0267Sriastradh return (ret < 0) ? ret : 0;
604*41ec0267Sriastradh }
605*41ec0267Sriastradh EXPORT_SYMBOL(mipi_dsi_picture_parameter_set);
606*41ec0267Sriastradh
607*41ec0267Sriastradh /**
608efa246c0Sriastradh * mipi_dsi_generic_write() - transmit data using a generic write packet
609efa246c0Sriastradh * @dsi: DSI peripheral device
610efa246c0Sriastradh * @payload: buffer containing the payload
611efa246c0Sriastradh * @size: size of payload buffer
612efa246c0Sriastradh *
613efa246c0Sriastradh * This function will automatically choose the right data type depending on
614efa246c0Sriastradh * the payload length.
615efa246c0Sriastradh *
616efa246c0Sriastradh * Return: The number of bytes transmitted on success or a negative error code
617efa246c0Sriastradh * on failure.
618efa246c0Sriastradh */
mipi_dsi_generic_write(struct mipi_dsi_device * dsi,const void * payload,size_t size)619efa246c0Sriastradh ssize_t mipi_dsi_generic_write(struct mipi_dsi_device *dsi, const void *payload,
620efa246c0Sriastradh size_t size)
621efa246c0Sriastradh {
622efa246c0Sriastradh struct mipi_dsi_msg msg = {
623efa246c0Sriastradh .channel = dsi->channel,
624efa246c0Sriastradh .tx_buf = payload,
625efa246c0Sriastradh .tx_len = size
626efa246c0Sriastradh };
627efa246c0Sriastradh
628efa246c0Sriastradh switch (size) {
629efa246c0Sriastradh case 0:
630efa246c0Sriastradh msg.type = MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM;
631efa246c0Sriastradh break;
632efa246c0Sriastradh
633efa246c0Sriastradh case 1:
634efa246c0Sriastradh msg.type = MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM;
635efa246c0Sriastradh break;
636efa246c0Sriastradh
637efa246c0Sriastradh case 2:
638efa246c0Sriastradh msg.type = MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM;
639efa246c0Sriastradh break;
640efa246c0Sriastradh
641efa246c0Sriastradh default:
642efa246c0Sriastradh msg.type = MIPI_DSI_GENERIC_LONG_WRITE;
643efa246c0Sriastradh break;
644efa246c0Sriastradh }
645efa246c0Sriastradh
646efa246c0Sriastradh return mipi_dsi_device_transfer(dsi, &msg);
647efa246c0Sriastradh }
648efa246c0Sriastradh EXPORT_SYMBOL(mipi_dsi_generic_write);
649efa246c0Sriastradh
650efa246c0Sriastradh /**
651efa246c0Sriastradh * mipi_dsi_generic_read() - receive data using a generic read packet
652efa246c0Sriastradh * @dsi: DSI peripheral device
653efa246c0Sriastradh * @params: buffer containing the request parameters
654efa246c0Sriastradh * @num_params: number of request parameters
655efa246c0Sriastradh * @data: buffer in which to return the received data
656efa246c0Sriastradh * @size: size of receive buffer
657efa246c0Sriastradh *
658efa246c0Sriastradh * This function will automatically choose the right data type depending on
659efa246c0Sriastradh * the number of parameters passed in.
660efa246c0Sriastradh *
661efa246c0Sriastradh * Return: The number of bytes successfully read or a negative error code on
662efa246c0Sriastradh * failure.
663efa246c0Sriastradh */
mipi_dsi_generic_read(struct mipi_dsi_device * dsi,const void * params,size_t num_params,void * data,size_t size)664efa246c0Sriastradh ssize_t mipi_dsi_generic_read(struct mipi_dsi_device *dsi, const void *params,
665efa246c0Sriastradh size_t num_params, void *data, size_t size)
666efa246c0Sriastradh {
667efa246c0Sriastradh struct mipi_dsi_msg msg = {
668efa246c0Sriastradh .channel = dsi->channel,
669efa246c0Sriastradh .tx_len = num_params,
670efa246c0Sriastradh .tx_buf = params,
671efa246c0Sriastradh .rx_len = size,
672efa246c0Sriastradh .rx_buf = data
673efa246c0Sriastradh };
674efa246c0Sriastradh
675efa246c0Sriastradh switch (num_params) {
676efa246c0Sriastradh case 0:
677efa246c0Sriastradh msg.type = MIPI_DSI_GENERIC_READ_REQUEST_0_PARAM;
678efa246c0Sriastradh break;
679efa246c0Sriastradh
680efa246c0Sriastradh case 1:
681efa246c0Sriastradh msg.type = MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM;
682efa246c0Sriastradh break;
683efa246c0Sriastradh
684efa246c0Sriastradh case 2:
685efa246c0Sriastradh msg.type = MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM;
686efa246c0Sriastradh break;
687efa246c0Sriastradh
688efa246c0Sriastradh default:
689efa246c0Sriastradh return -EINVAL;
690efa246c0Sriastradh }
691efa246c0Sriastradh
692efa246c0Sriastradh return mipi_dsi_device_transfer(dsi, &msg);
693efa246c0Sriastradh }
694efa246c0Sriastradh EXPORT_SYMBOL(mipi_dsi_generic_read);
695efa246c0Sriastradh
696efa246c0Sriastradh /**
697efa246c0Sriastradh * mipi_dsi_dcs_write_buffer() - transmit a DCS command with payload
698efa246c0Sriastradh * @dsi: DSI peripheral device
699efa246c0Sriastradh * @data: buffer containing data to be transmitted
700efa246c0Sriastradh * @len: size of transmission buffer
701efa246c0Sriastradh *
702efa246c0Sriastradh * This function will automatically choose the right data type depending on
703efa246c0Sriastradh * the command payload length.
704efa246c0Sriastradh *
705efa246c0Sriastradh * Return: The number of bytes successfully transmitted or a negative error
706efa246c0Sriastradh * code on failure.
707efa246c0Sriastradh */
mipi_dsi_dcs_write_buffer(struct mipi_dsi_device * dsi,const void * data,size_t len)708efa246c0Sriastradh ssize_t mipi_dsi_dcs_write_buffer(struct mipi_dsi_device *dsi,
709efa246c0Sriastradh const void *data, size_t len)
710efa246c0Sriastradh {
711efa246c0Sriastradh struct mipi_dsi_msg msg = {
712efa246c0Sriastradh .channel = dsi->channel,
713efa246c0Sriastradh .tx_buf = data,
714efa246c0Sriastradh .tx_len = len
715efa246c0Sriastradh };
716efa246c0Sriastradh
7179d20d926Sriastradh switch (len) {
7189d20d926Sriastradh case 0:
7199d20d926Sriastradh return -EINVAL;
720efa246c0Sriastradh
7219d20d926Sriastradh case 1:
7229d20d926Sriastradh msg.type = MIPI_DSI_DCS_SHORT_WRITE;
7239d20d926Sriastradh break;
724efa246c0Sriastradh
7259d20d926Sriastradh case 2:
7269d20d926Sriastradh msg.type = MIPI_DSI_DCS_SHORT_WRITE_PARAM;
7279d20d926Sriastradh break;
728efa246c0Sriastradh
7299d20d926Sriastradh default:
7309d20d926Sriastradh msg.type = MIPI_DSI_DCS_LONG_WRITE;
7319d20d926Sriastradh break;
7329d20d926Sriastradh }
7339d20d926Sriastradh
734efa246c0Sriastradh return mipi_dsi_device_transfer(dsi, &msg);
735efa246c0Sriastradh }
736efa246c0Sriastradh EXPORT_SYMBOL(mipi_dsi_dcs_write_buffer);
737efa246c0Sriastradh
738efa246c0Sriastradh /**
739efa246c0Sriastradh * mipi_dsi_dcs_write() - send DCS write command
740efa246c0Sriastradh * @dsi: DSI peripheral device
741efa246c0Sriastradh * @cmd: DCS command
742efa246c0Sriastradh * @data: buffer containing the command payload
743efa246c0Sriastradh * @len: command payload length
744efa246c0Sriastradh *
745efa246c0Sriastradh * This function will automatically choose the right data type depending on
746efa246c0Sriastradh * the command payload length.
747efa246c0Sriastradh *
748efa246c0Sriastradh * Return: The number of bytes successfully transmitted or a negative error
749efa246c0Sriastradh * code on failure.
750efa246c0Sriastradh */
mipi_dsi_dcs_write(struct mipi_dsi_device * dsi,u8 cmd,const void * data,size_t len)751efa246c0Sriastradh ssize_t mipi_dsi_dcs_write(struct mipi_dsi_device *dsi, u8 cmd,
752efa246c0Sriastradh const void *data, size_t len)
753efa246c0Sriastradh {
754efa246c0Sriastradh ssize_t err;
755efa246c0Sriastradh size_t size;
756efa246c0Sriastradh u8 *tx;
757efa246c0Sriastradh
758efa246c0Sriastradh if (len > 0) {
759efa246c0Sriastradh size = 1 + len;
760efa246c0Sriastradh
761efa246c0Sriastradh tx = kmalloc(size, GFP_KERNEL);
762efa246c0Sriastradh if (!tx)
763efa246c0Sriastradh return -ENOMEM;
764efa246c0Sriastradh
765efa246c0Sriastradh /* concatenate the DCS command byte and the payload */
766efa246c0Sriastradh tx[0] = cmd;
767efa246c0Sriastradh memcpy(&tx[1], data, len);
768efa246c0Sriastradh } else {
769efa246c0Sriastradh tx = &cmd;
770efa246c0Sriastradh size = 1;
771efa246c0Sriastradh }
772efa246c0Sriastradh
773efa246c0Sriastradh err = mipi_dsi_dcs_write_buffer(dsi, tx, size);
774efa246c0Sriastradh
775efa246c0Sriastradh if (len > 0)
776efa246c0Sriastradh kfree(tx);
777efa246c0Sriastradh
778efa246c0Sriastradh return err;
7799d20d926Sriastradh }
7809d20d926Sriastradh EXPORT_SYMBOL(mipi_dsi_dcs_write);
7819d20d926Sriastradh
7829d20d926Sriastradh /**
783efa246c0Sriastradh * mipi_dsi_dcs_read() - send DCS read request command
784efa246c0Sriastradh * @dsi: DSI peripheral device
785efa246c0Sriastradh * @cmd: DCS command
786efa246c0Sriastradh * @data: buffer in which to receive data
787efa246c0Sriastradh * @len: size of receive buffer
7889d20d926Sriastradh *
789efa246c0Sriastradh * Return: The number of bytes read or a negative error code on failure.
7909d20d926Sriastradh */
mipi_dsi_dcs_read(struct mipi_dsi_device * dsi,u8 cmd,void * data,size_t len)791efa246c0Sriastradh ssize_t mipi_dsi_dcs_read(struct mipi_dsi_device *dsi, u8 cmd, void *data,
792efa246c0Sriastradh size_t len)
7939d20d926Sriastradh {
7949d20d926Sriastradh struct mipi_dsi_msg msg = {
795efa246c0Sriastradh .channel = dsi->channel,
7969d20d926Sriastradh .type = MIPI_DSI_DCS_READ,
7979d20d926Sriastradh .tx_buf = &cmd,
7989d20d926Sriastradh .tx_len = 1,
7999d20d926Sriastradh .rx_buf = data,
8009d20d926Sriastradh .rx_len = len
8019d20d926Sriastradh };
8029d20d926Sriastradh
803efa246c0Sriastradh return mipi_dsi_device_transfer(dsi, &msg);
8049d20d926Sriastradh }
8059d20d926Sriastradh EXPORT_SYMBOL(mipi_dsi_dcs_read);
8069d20d926Sriastradh
807efa246c0Sriastradh /**
808efa246c0Sriastradh * mipi_dsi_dcs_nop() - send DCS nop packet
809efa246c0Sriastradh * @dsi: DSI peripheral device
810efa246c0Sriastradh *
811efa246c0Sriastradh * Return: 0 on success or a negative error code on failure.
812efa246c0Sriastradh */
mipi_dsi_dcs_nop(struct mipi_dsi_device * dsi)813efa246c0Sriastradh int mipi_dsi_dcs_nop(struct mipi_dsi_device *dsi)
814efa246c0Sriastradh {
815efa246c0Sriastradh ssize_t err;
816efa246c0Sriastradh
817efa246c0Sriastradh err = mipi_dsi_dcs_write(dsi, MIPI_DCS_NOP, NULL, 0);
818efa246c0Sriastradh if (err < 0)
819efa246c0Sriastradh return err;
820efa246c0Sriastradh
821efa246c0Sriastradh return 0;
822efa246c0Sriastradh }
823efa246c0Sriastradh EXPORT_SYMBOL(mipi_dsi_dcs_nop);
824efa246c0Sriastradh
825efa246c0Sriastradh /**
826efa246c0Sriastradh * mipi_dsi_dcs_soft_reset() - perform a software reset of the display module
827efa246c0Sriastradh * @dsi: DSI peripheral device
828efa246c0Sriastradh *
829efa246c0Sriastradh * Return: 0 on success or a negative error code on failure.
830efa246c0Sriastradh */
mipi_dsi_dcs_soft_reset(struct mipi_dsi_device * dsi)831efa246c0Sriastradh int mipi_dsi_dcs_soft_reset(struct mipi_dsi_device *dsi)
832efa246c0Sriastradh {
833efa246c0Sriastradh ssize_t err;
834efa246c0Sriastradh
835efa246c0Sriastradh err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SOFT_RESET, NULL, 0);
836efa246c0Sriastradh if (err < 0)
837efa246c0Sriastradh return err;
838efa246c0Sriastradh
839efa246c0Sriastradh return 0;
840efa246c0Sriastradh }
841efa246c0Sriastradh EXPORT_SYMBOL(mipi_dsi_dcs_soft_reset);
842efa246c0Sriastradh
843efa246c0Sriastradh /**
844efa246c0Sriastradh * mipi_dsi_dcs_get_power_mode() - query the display module's current power
845efa246c0Sriastradh * mode
846efa246c0Sriastradh * @dsi: DSI peripheral device
847efa246c0Sriastradh * @mode: return location for the current power mode
848efa246c0Sriastradh *
849efa246c0Sriastradh * Return: 0 on success or a negative error code on failure.
850efa246c0Sriastradh */
mipi_dsi_dcs_get_power_mode(struct mipi_dsi_device * dsi,u8 * mode)851efa246c0Sriastradh int mipi_dsi_dcs_get_power_mode(struct mipi_dsi_device *dsi, u8 *mode)
852efa246c0Sriastradh {
853efa246c0Sriastradh ssize_t err;
854efa246c0Sriastradh
855efa246c0Sriastradh err = mipi_dsi_dcs_read(dsi, MIPI_DCS_GET_POWER_MODE, mode,
856efa246c0Sriastradh sizeof(*mode));
857efa246c0Sriastradh if (err <= 0) {
858efa246c0Sriastradh if (err == 0)
859efa246c0Sriastradh err = -ENODATA;
860efa246c0Sriastradh
861efa246c0Sriastradh return err;
862efa246c0Sriastradh }
863efa246c0Sriastradh
864efa246c0Sriastradh return 0;
865efa246c0Sriastradh }
866efa246c0Sriastradh EXPORT_SYMBOL(mipi_dsi_dcs_get_power_mode);
867efa246c0Sriastradh
868efa246c0Sriastradh /**
869efa246c0Sriastradh * mipi_dsi_dcs_get_pixel_format() - gets the pixel format for the RGB image
870efa246c0Sriastradh * data used by the interface
871efa246c0Sriastradh * @dsi: DSI peripheral device
872efa246c0Sriastradh * @format: return location for the pixel format
873efa246c0Sriastradh *
874efa246c0Sriastradh * Return: 0 on success or a negative error code on failure.
875efa246c0Sriastradh */
mipi_dsi_dcs_get_pixel_format(struct mipi_dsi_device * dsi,u8 * format)876efa246c0Sriastradh int mipi_dsi_dcs_get_pixel_format(struct mipi_dsi_device *dsi, u8 *format)
877efa246c0Sriastradh {
878efa246c0Sriastradh ssize_t err;
879efa246c0Sriastradh
880efa246c0Sriastradh err = mipi_dsi_dcs_read(dsi, MIPI_DCS_GET_PIXEL_FORMAT, format,
881efa246c0Sriastradh sizeof(*format));
882efa246c0Sriastradh if (err <= 0) {
883efa246c0Sriastradh if (err == 0)
884efa246c0Sriastradh err = -ENODATA;
885efa246c0Sriastradh
886efa246c0Sriastradh return err;
887efa246c0Sriastradh }
888efa246c0Sriastradh
889efa246c0Sriastradh return 0;
890efa246c0Sriastradh }
891efa246c0Sriastradh EXPORT_SYMBOL(mipi_dsi_dcs_get_pixel_format);
892efa246c0Sriastradh
893efa246c0Sriastradh /**
894efa246c0Sriastradh * mipi_dsi_dcs_enter_sleep_mode() - disable all unnecessary blocks inside the
895efa246c0Sriastradh * display module except interface communication
896efa246c0Sriastradh * @dsi: DSI peripheral device
897efa246c0Sriastradh *
898efa246c0Sriastradh * Return: 0 on success or a negative error code on failure.
899efa246c0Sriastradh */
mipi_dsi_dcs_enter_sleep_mode(struct mipi_dsi_device * dsi)900efa246c0Sriastradh int mipi_dsi_dcs_enter_sleep_mode(struct mipi_dsi_device *dsi)
901efa246c0Sriastradh {
902efa246c0Sriastradh ssize_t err;
903efa246c0Sriastradh
904efa246c0Sriastradh err = mipi_dsi_dcs_write(dsi, MIPI_DCS_ENTER_SLEEP_MODE, NULL, 0);
905efa246c0Sriastradh if (err < 0)
906efa246c0Sriastradh return err;
907efa246c0Sriastradh
908efa246c0Sriastradh return 0;
909efa246c0Sriastradh }
910efa246c0Sriastradh EXPORT_SYMBOL(mipi_dsi_dcs_enter_sleep_mode);
911efa246c0Sriastradh
912efa246c0Sriastradh /**
913efa246c0Sriastradh * mipi_dsi_dcs_exit_sleep_mode() - enable all blocks inside the display
914efa246c0Sriastradh * module
915efa246c0Sriastradh * @dsi: DSI peripheral device
916efa246c0Sriastradh *
917efa246c0Sriastradh * Return: 0 on success or a negative error code on failure.
918efa246c0Sriastradh */
mipi_dsi_dcs_exit_sleep_mode(struct mipi_dsi_device * dsi)919efa246c0Sriastradh int mipi_dsi_dcs_exit_sleep_mode(struct mipi_dsi_device *dsi)
920efa246c0Sriastradh {
921efa246c0Sriastradh ssize_t err;
922efa246c0Sriastradh
923efa246c0Sriastradh err = mipi_dsi_dcs_write(dsi, MIPI_DCS_EXIT_SLEEP_MODE, NULL, 0);
924efa246c0Sriastradh if (err < 0)
925efa246c0Sriastradh return err;
926efa246c0Sriastradh
927efa246c0Sriastradh return 0;
928efa246c0Sriastradh }
929efa246c0Sriastradh EXPORT_SYMBOL(mipi_dsi_dcs_exit_sleep_mode);
930efa246c0Sriastradh
931efa246c0Sriastradh /**
932efa246c0Sriastradh * mipi_dsi_dcs_set_display_off() - stop displaying the image data on the
933efa246c0Sriastradh * display device
934efa246c0Sriastradh * @dsi: DSI peripheral device
935efa246c0Sriastradh *
936efa246c0Sriastradh * Return: 0 on success or a negative error code on failure.
937efa246c0Sriastradh */
mipi_dsi_dcs_set_display_off(struct mipi_dsi_device * dsi)938efa246c0Sriastradh int mipi_dsi_dcs_set_display_off(struct mipi_dsi_device *dsi)
939efa246c0Sriastradh {
940efa246c0Sriastradh ssize_t err;
941efa246c0Sriastradh
942efa246c0Sriastradh err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_DISPLAY_OFF, NULL, 0);
943efa246c0Sriastradh if (err < 0)
944efa246c0Sriastradh return err;
945efa246c0Sriastradh
946efa246c0Sriastradh return 0;
947efa246c0Sriastradh }
948efa246c0Sriastradh EXPORT_SYMBOL(mipi_dsi_dcs_set_display_off);
949efa246c0Sriastradh
950efa246c0Sriastradh /**
951efa246c0Sriastradh * mipi_dsi_dcs_set_display_on() - start displaying the image data on the
952efa246c0Sriastradh * display device
953efa246c0Sriastradh * @dsi: DSI peripheral device
954efa246c0Sriastradh *
955efa246c0Sriastradh * Return: 0 on success or a negative error code on failure
956efa246c0Sriastradh */
mipi_dsi_dcs_set_display_on(struct mipi_dsi_device * dsi)957efa246c0Sriastradh int mipi_dsi_dcs_set_display_on(struct mipi_dsi_device *dsi)
958efa246c0Sriastradh {
959efa246c0Sriastradh ssize_t err;
960efa246c0Sriastradh
961efa246c0Sriastradh err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_DISPLAY_ON, NULL, 0);
962efa246c0Sriastradh if (err < 0)
963efa246c0Sriastradh return err;
964efa246c0Sriastradh
965efa246c0Sriastradh return 0;
966efa246c0Sriastradh }
967efa246c0Sriastradh EXPORT_SYMBOL(mipi_dsi_dcs_set_display_on);
968efa246c0Sriastradh
969efa246c0Sriastradh /**
970efa246c0Sriastradh * mipi_dsi_dcs_set_column_address() - define the column extent of the frame
971efa246c0Sriastradh * memory accessed by the host processor
972efa246c0Sriastradh * @dsi: DSI peripheral device
973efa246c0Sriastradh * @start: first column of frame memory
974efa246c0Sriastradh * @end: last column of frame memory
975efa246c0Sriastradh *
976efa246c0Sriastradh * Return: 0 on success or a negative error code on failure.
977efa246c0Sriastradh */
mipi_dsi_dcs_set_column_address(struct mipi_dsi_device * dsi,u16 start,u16 end)978efa246c0Sriastradh int mipi_dsi_dcs_set_column_address(struct mipi_dsi_device *dsi, u16 start,
979efa246c0Sriastradh u16 end)
980efa246c0Sriastradh {
981efa246c0Sriastradh u8 payload[4] = { start >> 8, start & 0xff, end >> 8, end & 0xff };
982efa246c0Sriastradh ssize_t err;
983efa246c0Sriastradh
984efa246c0Sriastradh err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_COLUMN_ADDRESS, payload,
985efa246c0Sriastradh sizeof(payload));
986efa246c0Sriastradh if (err < 0)
987efa246c0Sriastradh return err;
988efa246c0Sriastradh
989efa246c0Sriastradh return 0;
990efa246c0Sriastradh }
991efa246c0Sriastradh EXPORT_SYMBOL(mipi_dsi_dcs_set_column_address);
992efa246c0Sriastradh
993efa246c0Sriastradh /**
994efa246c0Sriastradh * mipi_dsi_dcs_set_page_address() - define the page extent of the frame
995efa246c0Sriastradh * memory accessed by the host processor
996efa246c0Sriastradh * @dsi: DSI peripheral device
997efa246c0Sriastradh * @start: first page of frame memory
998efa246c0Sriastradh * @end: last page of frame memory
999efa246c0Sriastradh *
1000efa246c0Sriastradh * Return: 0 on success or a negative error code on failure.
1001efa246c0Sriastradh */
mipi_dsi_dcs_set_page_address(struct mipi_dsi_device * dsi,u16 start,u16 end)1002efa246c0Sriastradh int mipi_dsi_dcs_set_page_address(struct mipi_dsi_device *dsi, u16 start,
1003efa246c0Sriastradh u16 end)
1004efa246c0Sriastradh {
1005efa246c0Sriastradh u8 payload[4] = { start >> 8, start & 0xff, end >> 8, end & 0xff };
1006efa246c0Sriastradh ssize_t err;
1007efa246c0Sriastradh
1008efa246c0Sriastradh err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_PAGE_ADDRESS, payload,
1009efa246c0Sriastradh sizeof(payload));
1010efa246c0Sriastradh if (err < 0)
1011efa246c0Sriastradh return err;
1012efa246c0Sriastradh
1013efa246c0Sriastradh return 0;
1014efa246c0Sriastradh }
1015efa246c0Sriastradh EXPORT_SYMBOL(mipi_dsi_dcs_set_page_address);
1016efa246c0Sriastradh
1017efa246c0Sriastradh /**
1018efa246c0Sriastradh * mipi_dsi_dcs_set_tear_off() - turn off the display module's Tearing Effect
1019efa246c0Sriastradh * output signal on the TE signal line
1020efa246c0Sriastradh * @dsi: DSI peripheral device
1021efa246c0Sriastradh *
1022efa246c0Sriastradh * Return: 0 on success or a negative error code on failure
1023efa246c0Sriastradh */
mipi_dsi_dcs_set_tear_off(struct mipi_dsi_device * dsi)1024efa246c0Sriastradh int mipi_dsi_dcs_set_tear_off(struct mipi_dsi_device *dsi)
1025efa246c0Sriastradh {
1026efa246c0Sriastradh ssize_t err;
1027efa246c0Sriastradh
1028efa246c0Sriastradh err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_TEAR_OFF, NULL, 0);
1029efa246c0Sriastradh if (err < 0)
1030efa246c0Sriastradh return err;
1031efa246c0Sriastradh
1032efa246c0Sriastradh return 0;
1033efa246c0Sriastradh }
1034efa246c0Sriastradh EXPORT_SYMBOL(mipi_dsi_dcs_set_tear_off);
1035efa246c0Sriastradh
1036efa246c0Sriastradh /**
1037efa246c0Sriastradh * mipi_dsi_dcs_set_tear_on() - turn on the display module's Tearing Effect
1038efa246c0Sriastradh * output signal on the TE signal line.
1039efa246c0Sriastradh * @dsi: DSI peripheral device
1040efa246c0Sriastradh * @mode: the Tearing Effect Output Line mode
1041efa246c0Sriastradh *
1042efa246c0Sriastradh * Return: 0 on success or a negative error code on failure
1043efa246c0Sriastradh */
mipi_dsi_dcs_set_tear_on(struct mipi_dsi_device * dsi,enum mipi_dsi_dcs_tear_mode mode)1044efa246c0Sriastradh int mipi_dsi_dcs_set_tear_on(struct mipi_dsi_device *dsi,
1045efa246c0Sriastradh enum mipi_dsi_dcs_tear_mode mode)
1046efa246c0Sriastradh {
1047efa246c0Sriastradh u8 value = mode;
1048efa246c0Sriastradh ssize_t err;
1049efa246c0Sriastradh
1050efa246c0Sriastradh err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_TEAR_ON, &value,
1051efa246c0Sriastradh sizeof(value));
1052efa246c0Sriastradh if (err < 0)
1053efa246c0Sriastradh return err;
1054efa246c0Sriastradh
1055efa246c0Sriastradh return 0;
1056efa246c0Sriastradh }
1057efa246c0Sriastradh EXPORT_SYMBOL(mipi_dsi_dcs_set_tear_on);
1058efa246c0Sriastradh
1059efa246c0Sriastradh /**
1060efa246c0Sriastradh * mipi_dsi_dcs_set_pixel_format() - sets the pixel format for the RGB image
1061efa246c0Sriastradh * data used by the interface
1062efa246c0Sriastradh * @dsi: DSI peripheral device
1063efa246c0Sriastradh * @format: pixel format
1064efa246c0Sriastradh *
1065efa246c0Sriastradh * Return: 0 on success or a negative error code on failure.
1066efa246c0Sriastradh */
mipi_dsi_dcs_set_pixel_format(struct mipi_dsi_device * dsi,u8 format)1067efa246c0Sriastradh int mipi_dsi_dcs_set_pixel_format(struct mipi_dsi_device *dsi, u8 format)
1068efa246c0Sriastradh {
1069efa246c0Sriastradh ssize_t err;
1070efa246c0Sriastradh
1071efa246c0Sriastradh err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_PIXEL_FORMAT, &format,
1072efa246c0Sriastradh sizeof(format));
1073efa246c0Sriastradh if (err < 0)
1074efa246c0Sriastradh return err;
1075efa246c0Sriastradh
1076efa246c0Sriastradh return 0;
1077efa246c0Sriastradh }
1078efa246c0Sriastradh EXPORT_SYMBOL(mipi_dsi_dcs_set_pixel_format);
1079efa246c0Sriastradh
1080*41ec0267Sriastradh /**
1081*41ec0267Sriastradh * mipi_dsi_dcs_set_tear_scanline() - set the scanline to use as trigger for
1082*41ec0267Sriastradh * the Tearing Effect output signal of the display module
1083*41ec0267Sriastradh * @dsi: DSI peripheral device
1084*41ec0267Sriastradh * @scanline: scanline to use as trigger
1085*41ec0267Sriastradh *
1086*41ec0267Sriastradh * Return: 0 on success or a negative error code on failure
1087*41ec0267Sriastradh */
mipi_dsi_dcs_set_tear_scanline(struct mipi_dsi_device * dsi,u16 scanline)1088*41ec0267Sriastradh int mipi_dsi_dcs_set_tear_scanline(struct mipi_dsi_device *dsi, u16 scanline)
1089*41ec0267Sriastradh {
1090*41ec0267Sriastradh u8 payload[3] = { MIPI_DCS_SET_TEAR_SCANLINE, scanline >> 8,
1091*41ec0267Sriastradh scanline & 0xff };
1092*41ec0267Sriastradh ssize_t err;
1093*41ec0267Sriastradh
1094*41ec0267Sriastradh err = mipi_dsi_generic_write(dsi, payload, sizeof(payload));
1095*41ec0267Sriastradh if (err < 0)
1096*41ec0267Sriastradh return err;
1097*41ec0267Sriastradh
1098*41ec0267Sriastradh return 0;
1099*41ec0267Sriastradh }
1100*41ec0267Sriastradh EXPORT_SYMBOL(mipi_dsi_dcs_set_tear_scanline);
1101*41ec0267Sriastradh
1102*41ec0267Sriastradh /**
1103*41ec0267Sriastradh * mipi_dsi_dcs_set_display_brightness() - sets the brightness value of the
1104*41ec0267Sriastradh * display
1105*41ec0267Sriastradh * @dsi: DSI peripheral device
1106*41ec0267Sriastradh * @brightness: brightness value
1107*41ec0267Sriastradh *
1108*41ec0267Sriastradh * Return: 0 on success or a negative error code on failure.
1109*41ec0267Sriastradh */
mipi_dsi_dcs_set_display_brightness(struct mipi_dsi_device * dsi,u16 brightness)1110*41ec0267Sriastradh int mipi_dsi_dcs_set_display_brightness(struct mipi_dsi_device *dsi,
1111*41ec0267Sriastradh u16 brightness)
1112*41ec0267Sriastradh {
1113*41ec0267Sriastradh u8 payload[2] = { brightness & 0xff, brightness >> 8 };
1114*41ec0267Sriastradh ssize_t err;
1115*41ec0267Sriastradh
1116*41ec0267Sriastradh err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_DISPLAY_BRIGHTNESS,
1117*41ec0267Sriastradh payload, sizeof(payload));
1118*41ec0267Sriastradh if (err < 0)
1119*41ec0267Sriastradh return err;
1120*41ec0267Sriastradh
1121*41ec0267Sriastradh return 0;
1122*41ec0267Sriastradh }
1123*41ec0267Sriastradh EXPORT_SYMBOL(mipi_dsi_dcs_set_display_brightness);
1124*41ec0267Sriastradh
1125*41ec0267Sriastradh /**
1126*41ec0267Sriastradh * mipi_dsi_dcs_get_display_brightness() - gets the current brightness value
1127*41ec0267Sriastradh * of the display
1128*41ec0267Sriastradh * @dsi: DSI peripheral device
1129*41ec0267Sriastradh * @brightness: brightness value
1130*41ec0267Sriastradh *
1131*41ec0267Sriastradh * Return: 0 on success or a negative error code on failure.
1132*41ec0267Sriastradh */
mipi_dsi_dcs_get_display_brightness(struct mipi_dsi_device * dsi,u16 * brightness)1133*41ec0267Sriastradh int mipi_dsi_dcs_get_display_brightness(struct mipi_dsi_device *dsi,
1134*41ec0267Sriastradh u16 *brightness)
1135*41ec0267Sriastradh {
1136*41ec0267Sriastradh ssize_t err;
1137*41ec0267Sriastradh
1138*41ec0267Sriastradh err = mipi_dsi_dcs_read(dsi, MIPI_DCS_GET_DISPLAY_BRIGHTNESS,
1139*41ec0267Sriastradh brightness, sizeof(*brightness));
1140*41ec0267Sriastradh if (err <= 0) {
1141*41ec0267Sriastradh if (err == 0)
1142*41ec0267Sriastradh err = -ENODATA;
1143*41ec0267Sriastradh
1144*41ec0267Sriastradh return err;
1145*41ec0267Sriastradh }
1146*41ec0267Sriastradh
1147*41ec0267Sriastradh return 0;
1148*41ec0267Sriastradh }
1149*41ec0267Sriastradh EXPORT_SYMBOL(mipi_dsi_dcs_get_display_brightness);
1150*41ec0267Sriastradh
mipi_dsi_drv_probe(struct device * dev)11519d20d926Sriastradh static int mipi_dsi_drv_probe(struct device *dev)
11529d20d926Sriastradh {
11539d20d926Sriastradh struct mipi_dsi_driver *drv = to_mipi_dsi_driver(dev->driver);
11549d20d926Sriastradh struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev);
11559d20d926Sriastradh
11569d20d926Sriastradh return drv->probe(dsi);
11579d20d926Sriastradh }
11589d20d926Sriastradh
mipi_dsi_drv_remove(struct device * dev)11599d20d926Sriastradh static int mipi_dsi_drv_remove(struct device *dev)
11609d20d926Sriastradh {
11619d20d926Sriastradh struct mipi_dsi_driver *drv = to_mipi_dsi_driver(dev->driver);
11629d20d926Sriastradh struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev);
11639d20d926Sriastradh
11649d20d926Sriastradh return drv->remove(dsi);
11659d20d926Sriastradh }
11669d20d926Sriastradh
mipi_dsi_drv_shutdown(struct device * dev)1167efa246c0Sriastradh static void mipi_dsi_drv_shutdown(struct device *dev)
1168efa246c0Sriastradh {
1169efa246c0Sriastradh struct mipi_dsi_driver *drv = to_mipi_dsi_driver(dev->driver);
1170efa246c0Sriastradh struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev);
1171efa246c0Sriastradh
1172efa246c0Sriastradh drv->shutdown(dsi);
1173efa246c0Sriastradh }
1174efa246c0Sriastradh
11759d20d926Sriastradh /**
1176efa246c0Sriastradh * mipi_dsi_driver_register_full() - register a driver for DSI devices
11779d20d926Sriastradh * @drv: DSI driver structure
1178efa246c0Sriastradh * @owner: owner module
1179efa246c0Sriastradh *
1180efa246c0Sriastradh * Return: 0 on success or a negative error code on failure.
11819d20d926Sriastradh */
mipi_dsi_driver_register_full(struct mipi_dsi_driver * drv,struct module * owner)1182efa246c0Sriastradh int mipi_dsi_driver_register_full(struct mipi_dsi_driver *drv,
1183efa246c0Sriastradh struct module *owner)
11849d20d926Sriastradh {
11859d20d926Sriastradh drv->driver.bus = &mipi_dsi_bus_type;
1186efa246c0Sriastradh drv->driver.owner = owner;
1187efa246c0Sriastradh
11889d20d926Sriastradh if (drv->probe)
11899d20d926Sriastradh drv->driver.probe = mipi_dsi_drv_probe;
11909d20d926Sriastradh if (drv->remove)
11919d20d926Sriastradh drv->driver.remove = mipi_dsi_drv_remove;
1192efa246c0Sriastradh if (drv->shutdown)
1193efa246c0Sriastradh drv->driver.shutdown = mipi_dsi_drv_shutdown;
11949d20d926Sriastradh
11959d20d926Sriastradh return driver_register(&drv->driver);
11969d20d926Sriastradh }
1197efa246c0Sriastradh EXPORT_SYMBOL(mipi_dsi_driver_register_full);
11989d20d926Sriastradh
11999d20d926Sriastradh /**
1200efa246c0Sriastradh * mipi_dsi_driver_unregister() - unregister a driver for DSI devices
12019d20d926Sriastradh * @drv: DSI driver structure
1202efa246c0Sriastradh *
1203efa246c0Sriastradh * Return: 0 on success or a negative error code on failure.
12049d20d926Sriastradh */
mipi_dsi_driver_unregister(struct mipi_dsi_driver * drv)12059d20d926Sriastradh void mipi_dsi_driver_unregister(struct mipi_dsi_driver *drv)
12069d20d926Sriastradh {
12079d20d926Sriastradh driver_unregister(&drv->driver);
12089d20d926Sriastradh }
12099d20d926Sriastradh EXPORT_SYMBOL(mipi_dsi_driver_unregister);
12109d20d926Sriastradh
mipi_dsi_bus_init(void)12119d20d926Sriastradh static int __init mipi_dsi_bus_init(void)
12129d20d926Sriastradh {
12139d20d926Sriastradh return bus_register(&mipi_dsi_bus_type);
12149d20d926Sriastradh }
12159d20d926Sriastradh postcore_initcall(mipi_dsi_bus_init);
12169d20d926Sriastradh
12179d20d926Sriastradh MODULE_AUTHOR("Andrzej Hajda <a.hajda@samsung.com>");
12189d20d926Sriastradh MODULE_DESCRIPTION("MIPI DSI Bus");
12199d20d926Sriastradh MODULE_LICENSE("GPL and additional rights");
1220