Branch data Line data Source code
1 : : /*
2 : : * MIPI DSI Bus
3 : : *
4 : : * Copyright (C) 2012-2013, Samsung Electronics, Co., Ltd.
5 : : * Andrzej Hajda <a.hajda@samsung.com>
6 : : *
7 : : * Permission is hereby granted, free of charge, to any person obtaining a
8 : : * copy of this software and associated documentation files (the
9 : : * "Software"), to deal in the Software without restriction, including
10 : : * without limitation the rights to use, copy, modify, merge, publish,
11 : : * distribute, sub license, and/or sell copies of the Software, and to
12 : : * permit persons to whom the Software is furnished to do so, subject to
13 : : * the following conditions:
14 : : *
15 : : * The above copyright notice and this permission notice (including the
16 : : * next paragraph) shall be included in all copies or substantial portions
17 : : * of the Software.
18 : : *
19 : : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 : : * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 : : * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
22 : : * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
23 : : * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
24 : : * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
25 : : * USE OR OTHER DEALINGS IN THE SOFTWARE.
26 : : */
27 : :
28 : : #include <drm/drm_mipi_dsi.h>
29 : :
30 : : #include <linux/device.h>
31 : : #include <linux/module.h>
32 : : #include <linux/of_device.h>
33 : : #include <linux/pm_runtime.h>
34 : : #include <linux/slab.h>
35 : :
36 : : #include <drm/drm_dsc.h>
37 : : #include <video/mipi_display.h>
38 : :
39 : : /**
40 : : * DOC: dsi helpers
41 : : *
42 : : * These functions contain some common logic and helpers to deal with MIPI DSI
43 : : * peripherals.
44 : : *
45 : : * Helpers are provided for a number of standard MIPI DSI command as well as a
46 : : * subset of the MIPI DCS command set.
47 : : */
48 : :
49 : 0 : static int mipi_dsi_device_match(struct device *dev, struct device_driver *drv)
50 : : {
51 [ # # ]: 0 : struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev);
52 : :
53 : : /* attempt OF style match */
54 [ # # ]: 0 : if (of_driver_match_device(dev, drv))
55 : : return 1;
56 : :
57 : : /* compare DSI device and driver names */
58 [ # # ]: 0 : if (!strcmp(dsi->name, drv->name))
59 : 0 : return 1;
60 : :
61 : : return 0;
62 : : }
63 : :
64 : 0 : static int mipi_dsi_uevent(struct device *dev, struct kobj_uevent_env *env)
65 : : {
66 : 0 : struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev);
67 : 0 : int err;
68 : :
69 : 0 : err = of_device_uevent_modalias(dev, env);
70 : 0 : if (err != -ENODEV)
71 : : return err;
72 : :
73 : 0 : add_uevent_var(env, "MODALIAS=%s%s", MIPI_DSI_MODULE_PREFIX,
74 : 0 : dsi->name);
75 : :
76 : 0 : return 0;
77 : : }
78 : :
79 : : static const struct dev_pm_ops mipi_dsi_device_pm_ops = {
80 : : .runtime_suspend = pm_generic_runtime_suspend,
81 : : .runtime_resume = pm_generic_runtime_resume,
82 : : .suspend = pm_generic_suspend,
83 : : .resume = pm_generic_resume,
84 : : .freeze = pm_generic_freeze,
85 : : .thaw = pm_generic_thaw,
86 : : .poweroff = pm_generic_poweroff,
87 : : .restore = pm_generic_restore,
88 : : };
89 : :
90 : : static struct bus_type mipi_dsi_bus_type = {
91 : : .name = "mipi-dsi",
92 : : .match = mipi_dsi_device_match,
93 : : .uevent = mipi_dsi_uevent,
94 : : .pm = &mipi_dsi_device_pm_ops,
95 : : };
96 : :
97 : : /**
98 : : * of_find_mipi_dsi_device_by_node() - find the MIPI DSI device matching a
99 : : * device tree node
100 : : * @np: device tree node
101 : : *
102 : : * Return: A pointer to the MIPI DSI device corresponding to @np or NULL if no
103 : : * such device exists (or has not been registered yet).
104 : : */
105 : 0 : struct mipi_dsi_device *of_find_mipi_dsi_device_by_node(struct device_node *np)
106 : : {
107 : 0 : struct device *dev;
108 : :
109 : 0 : dev = bus_find_device_by_of_node(&mipi_dsi_bus_type, np);
110 : :
111 [ # # ]: 0 : return dev ? to_mipi_dsi_device(dev) : NULL;
112 : : }
113 : : EXPORT_SYMBOL(of_find_mipi_dsi_device_by_node);
114 : :
115 : 0 : static void mipi_dsi_dev_release(struct device *dev)
116 : : {
117 : 0 : struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev);
118 : :
119 : 0 : of_node_put(dev->of_node);
120 : 0 : kfree(dsi);
121 : 0 : }
122 : :
123 : : static const struct device_type mipi_dsi_device_type = {
124 : : .release = mipi_dsi_dev_release,
125 : : };
126 : :
127 : 0 : static struct mipi_dsi_device *mipi_dsi_device_alloc(struct mipi_dsi_host *host)
128 : : {
129 : 0 : struct mipi_dsi_device *dsi;
130 : :
131 : 0 : dsi = kzalloc(sizeof(*dsi), GFP_KERNEL);
132 [ # # ]: 0 : if (!dsi)
133 : : return ERR_PTR(-ENOMEM);
134 : :
135 : 0 : dsi->host = host;
136 : 0 : dsi->dev.bus = &mipi_dsi_bus_type;
137 : 0 : dsi->dev.parent = host->dev;
138 : 0 : dsi->dev.type = &mipi_dsi_device_type;
139 : :
140 : 0 : device_initialize(&dsi->dev);
141 : :
142 : 0 : return dsi;
143 : : }
144 : :
145 : 0 : static int mipi_dsi_device_add(struct mipi_dsi_device *dsi)
146 : : {
147 : 0 : struct mipi_dsi_host *host = dsi->host;
148 : :
149 [ # # ]: 0 : dev_set_name(&dsi->dev, "%s.%d", dev_name(host->dev), dsi->channel);
150 : :
151 : 0 : return device_add(&dsi->dev);
152 : : }
153 : :
154 : : #if IS_ENABLED(CONFIG_OF)
155 : : static struct mipi_dsi_device *
156 : : of_mipi_dsi_device_add(struct mipi_dsi_host *host, struct device_node *node)
157 : : {
158 : : struct device *dev = host->dev;
159 : : struct mipi_dsi_device_info info = { };
160 : : int ret;
161 : : u32 reg;
162 : :
163 : : if (of_modalias_node(node, info.type, sizeof(info.type)) < 0) {
164 : : dev_err(dev, "modalias failure on %pOF\n", node);
165 : : return ERR_PTR(-EINVAL);
166 : : }
167 : :
168 : : ret = of_property_read_u32(node, "reg", ®);
169 : : if (ret) {
170 : : dev_err(dev, "device node %pOF has no valid reg property: %d\n",
171 : : node, ret);
172 : : return ERR_PTR(-EINVAL);
173 : : }
174 : :
175 : : info.channel = reg;
176 : : info.node = of_node_get(node);
177 : :
178 : : return mipi_dsi_device_register_full(host, &info);
179 : : }
180 : : #else
181 : : static struct mipi_dsi_device *
182 : : of_mipi_dsi_device_add(struct mipi_dsi_host *host, struct device_node *node)
183 : : {
184 : : return ERR_PTR(-ENODEV);
185 : : }
186 : : #endif
187 : :
188 : : /**
189 : : * mipi_dsi_device_register_full - create a MIPI DSI device
190 : : * @host: DSI host to which this device is connected
191 : : * @info: pointer to template containing DSI device information
192 : : *
193 : : * Create a MIPI DSI device by using the device information provided by
194 : : * mipi_dsi_device_info template
195 : : *
196 : : * Returns:
197 : : * A pointer to the newly created MIPI DSI device, or, a pointer encoded
198 : : * with an error
199 : : */
200 : : struct mipi_dsi_device *
201 : 0 : mipi_dsi_device_register_full(struct mipi_dsi_host *host,
202 : : const struct mipi_dsi_device_info *info)
203 : : {
204 : 0 : struct mipi_dsi_device *dsi;
205 : 0 : struct device *dev = host->dev;
206 : 0 : int ret;
207 : :
208 [ # # ]: 0 : if (!info) {
209 : 0 : dev_err(dev, "invalid mipi_dsi_device_info pointer\n");
210 : 0 : return ERR_PTR(-EINVAL);
211 : : }
212 : :
213 [ # # ]: 0 : if (info->channel > 3) {
214 : 0 : dev_err(dev, "invalid virtual channel: %u\n", info->channel);
215 : 0 : return ERR_PTR(-EINVAL);
216 : : }
217 : :
218 : 0 : dsi = mipi_dsi_device_alloc(host);
219 [ # # ]: 0 : if (IS_ERR(dsi)) {
220 : 0 : dev_err(dev, "failed to allocate DSI device %ld\n",
221 : : PTR_ERR(dsi));
222 : 0 : return dsi;
223 : : }
224 : :
225 : 0 : dsi->dev.of_node = info->node;
226 : 0 : dsi->channel = info->channel;
227 : 0 : strlcpy(dsi->name, info->type, sizeof(dsi->name));
228 : :
229 : 0 : ret = mipi_dsi_device_add(dsi);
230 [ # # ]: 0 : if (ret) {
231 : 0 : dev_err(dev, "failed to add DSI device %d\n", ret);
232 : 0 : kfree(dsi);
233 : 0 : return ERR_PTR(ret);
234 : : }
235 : :
236 : : return dsi;
237 : : }
238 : : EXPORT_SYMBOL(mipi_dsi_device_register_full);
239 : :
240 : : /**
241 : : * mipi_dsi_device_unregister - unregister MIPI DSI device
242 : : * @dsi: DSI peripheral device
243 : : */
244 : 0 : void mipi_dsi_device_unregister(struct mipi_dsi_device *dsi)
245 : : {
246 : 0 : device_unregister(&dsi->dev);
247 : 0 : }
248 : : EXPORT_SYMBOL(mipi_dsi_device_unregister);
249 : :
250 : : static DEFINE_MUTEX(host_lock);
251 : : static LIST_HEAD(host_list);
252 : :
253 : : /**
254 : : * of_find_mipi_dsi_host_by_node() - find the MIPI DSI host matching a
255 : : * device tree node
256 : : * @node: device tree node
257 : : *
258 : : * Returns:
259 : : * A pointer to the MIPI DSI host corresponding to @node or NULL if no
260 : : * such device exists (or has not been registered yet).
261 : : */
262 : 0 : struct mipi_dsi_host *of_find_mipi_dsi_host_by_node(struct device_node *node)
263 : : {
264 : 0 : struct mipi_dsi_host *host;
265 : :
266 : 0 : mutex_lock(&host_lock);
267 : :
268 [ # # ]: 0 : list_for_each_entry(host, &host_list, list) {
269 [ # # ]: 0 : if (host->dev->of_node == node) {
270 : 0 : mutex_unlock(&host_lock);
271 : 0 : return host;
272 : : }
273 : : }
274 : :
275 : 0 : mutex_unlock(&host_lock);
276 : :
277 : 0 : return NULL;
278 : : }
279 : : EXPORT_SYMBOL(of_find_mipi_dsi_host_by_node);
280 : :
281 : 0 : int mipi_dsi_host_register(struct mipi_dsi_host *host)
282 : : {
283 : 0 : struct device_node *node;
284 : :
285 : 0 : for_each_available_child_of_node(host->dev->of_node, node) {
286 : : /* skip nodes without reg property */
287 : : if (!of_find_property(node, "reg", NULL))
288 : : continue;
289 : : of_mipi_dsi_device_add(host, node);
290 : : }
291 : :
292 : 0 : mutex_lock(&host_lock);
293 : 0 : list_add_tail(&host->list, &host_list);
294 : 0 : mutex_unlock(&host_lock);
295 : :
296 : 0 : return 0;
297 : : }
298 : : EXPORT_SYMBOL(mipi_dsi_host_register);
299 : :
300 : 0 : static int mipi_dsi_remove_device_fn(struct device *dev, void *priv)
301 : : {
302 : 0 : struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev);
303 : :
304 : 0 : mipi_dsi_device_unregister(dsi);
305 : :
306 : 0 : return 0;
307 : : }
308 : :
309 : 0 : void mipi_dsi_host_unregister(struct mipi_dsi_host *host)
310 : : {
311 : 0 : device_for_each_child(host->dev, NULL, mipi_dsi_remove_device_fn);
312 : :
313 : 0 : mutex_lock(&host_lock);
314 : 0 : list_del_init(&host->list);
315 : 0 : mutex_unlock(&host_lock);
316 : 0 : }
317 : : EXPORT_SYMBOL(mipi_dsi_host_unregister);
318 : :
319 : : /**
320 : : * mipi_dsi_attach - attach a DSI device to its DSI host
321 : : * @dsi: DSI peripheral
322 : : */
323 : 0 : int mipi_dsi_attach(struct mipi_dsi_device *dsi)
324 : : {
325 : 0 : const struct mipi_dsi_host_ops *ops = dsi->host->ops;
326 : :
327 [ # # # # ]: 0 : if (!ops || !ops->attach)
328 : : return -ENOSYS;
329 : :
330 : 0 : return ops->attach(dsi->host, dsi);
331 : : }
332 : : EXPORT_SYMBOL(mipi_dsi_attach);
333 : :
334 : : /**
335 : : * mipi_dsi_detach - detach a DSI device from its DSI host
336 : : * @dsi: DSI peripheral
337 : : */
338 : 0 : int mipi_dsi_detach(struct mipi_dsi_device *dsi)
339 : : {
340 : 0 : const struct mipi_dsi_host_ops *ops = dsi->host->ops;
341 : :
342 [ # # # # ]: 0 : if (!ops || !ops->detach)
343 : : return -ENOSYS;
344 : :
345 : 0 : return ops->detach(dsi->host, dsi);
346 : : }
347 : : EXPORT_SYMBOL(mipi_dsi_detach);
348 : :
349 : : static ssize_t mipi_dsi_device_transfer(struct mipi_dsi_device *dsi,
350 : : struct mipi_dsi_msg *msg)
351 : : {
352 : : const struct mipi_dsi_host_ops *ops = dsi->host->ops;
353 : :
354 : : if (!ops || !ops->transfer)
355 : : return -ENOSYS;
356 : :
357 : : if (dsi->mode_flags & MIPI_DSI_MODE_LPM)
358 : : msg->flags |= MIPI_DSI_MSG_USE_LPM;
359 : :
360 : : return ops->transfer(dsi->host, msg);
361 : : }
362 : :
363 : : /**
364 : : * mipi_dsi_packet_format_is_short - check if a packet is of the short format
365 : : * @type: MIPI DSI data type of the packet
366 : : *
367 : : * Return: true if the packet for the given data type is a short packet, false
368 : : * otherwise.
369 : : */
370 : 0 : bool mipi_dsi_packet_format_is_short(u8 type)
371 : : {
372 [ # # ]: 0 : switch (type) {
373 : : case MIPI_DSI_V_SYNC_START:
374 : : case MIPI_DSI_V_SYNC_END:
375 : : case MIPI_DSI_H_SYNC_START:
376 : : case MIPI_DSI_H_SYNC_END:
377 : : case MIPI_DSI_COMPRESSION_MODE:
378 : : case MIPI_DSI_END_OF_TRANSMISSION:
379 : : case MIPI_DSI_COLOR_MODE_OFF:
380 : : case MIPI_DSI_COLOR_MODE_ON:
381 : : case MIPI_DSI_SHUTDOWN_PERIPHERAL:
382 : : case MIPI_DSI_TURN_ON_PERIPHERAL:
383 : : case MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM:
384 : : case MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM:
385 : : case MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM:
386 : : case MIPI_DSI_GENERIC_READ_REQUEST_0_PARAM:
387 : : case MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM:
388 : : case MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM:
389 : : case MIPI_DSI_DCS_SHORT_WRITE:
390 : : case MIPI_DSI_DCS_SHORT_WRITE_PARAM:
391 : : case MIPI_DSI_DCS_READ:
392 : : case MIPI_DSI_EXECUTE_QUEUE:
393 : : case MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE:
394 : : return true;
395 : : }
396 : :
397 : 0 : return false;
398 : : }
399 : : EXPORT_SYMBOL(mipi_dsi_packet_format_is_short);
400 : :
401 : : /**
402 : : * mipi_dsi_packet_format_is_long - check if a packet is of the long format
403 : : * @type: MIPI DSI data type of the packet
404 : : *
405 : : * Return: true if the packet for the given data type is a long packet, false
406 : : * otherwise.
407 : : */
408 : 0 : bool mipi_dsi_packet_format_is_long(u8 type)
409 : : {
410 [ # # ]: 0 : switch (type) {
411 : : case MIPI_DSI_NULL_PACKET:
412 : : case MIPI_DSI_BLANKING_PACKET:
413 : : case MIPI_DSI_GENERIC_LONG_WRITE:
414 : : case MIPI_DSI_DCS_LONG_WRITE:
415 : : case MIPI_DSI_PICTURE_PARAMETER_SET:
416 : : case MIPI_DSI_COMPRESSED_PIXEL_STREAM:
417 : : case MIPI_DSI_LOOSELY_PACKED_PIXEL_STREAM_YCBCR20:
418 : : case MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR24:
419 : : case MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR16:
420 : : case MIPI_DSI_PACKED_PIXEL_STREAM_30:
421 : : case MIPI_DSI_PACKED_PIXEL_STREAM_36:
422 : : case MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR12:
423 : : case MIPI_DSI_PACKED_PIXEL_STREAM_16:
424 : : case MIPI_DSI_PACKED_PIXEL_STREAM_18:
425 : : case MIPI_DSI_PIXEL_STREAM_3BYTE_18:
426 : : case MIPI_DSI_PACKED_PIXEL_STREAM_24:
427 : : return true;
428 : : }
429 : :
430 : 0 : return false;
431 : : }
432 : : EXPORT_SYMBOL(mipi_dsi_packet_format_is_long);
433 : :
434 : : /**
435 : : * mipi_dsi_create_packet - create a packet from a message according to the
436 : : * DSI protocol
437 : : * @packet: pointer to a DSI packet structure
438 : : * @msg: message to translate into a packet
439 : : *
440 : : * Return: 0 on success or a negative error code on failure.
441 : : */
442 : 0 : int mipi_dsi_create_packet(struct mipi_dsi_packet *packet,
443 : : const struct mipi_dsi_msg *msg)
444 : : {
445 [ # # ]: 0 : if (!packet || !msg)
446 : : return -EINVAL;
447 : :
448 : : /* do some minimum sanity checking */
449 [ # # ]: 0 : if (!mipi_dsi_packet_format_is_short(msg->type) &&
450 [ # # ]: 0 : !mipi_dsi_packet_format_is_long(msg->type))
451 : : return -EINVAL;
452 : :
453 [ # # ]: 0 : if (msg->channel > 3)
454 : : return -EINVAL;
455 : :
456 : 0 : memset(packet, 0, sizeof(*packet));
457 : 0 : packet->header[0] = ((msg->channel & 0x3) << 6) | (msg->type & 0x3f);
458 : :
459 : : /* TODO: compute ECC if hardware support is not available */
460 : :
461 : : /*
462 : : * Long write packets contain the word count in header bytes 1 and 2.
463 : : * The payload follows the header and is word count bytes long.
464 : : *
465 : : * Short write packets encode up to two parameters in header bytes 1
466 : : * and 2.
467 : : */
468 [ # # ]: 0 : if (mipi_dsi_packet_format_is_long(msg->type)) {
469 : 0 : packet->header[1] = (msg->tx_len >> 0) & 0xff;
470 : 0 : packet->header[2] = (msg->tx_len >> 8) & 0xff;
471 : :
472 : 0 : packet->payload_length = msg->tx_len;
473 : 0 : packet->payload = msg->tx_buf;
474 : : } else {
475 : 0 : const u8 *tx = msg->tx_buf;
476 : :
477 [ # # ]: 0 : packet->header[1] = (msg->tx_len > 0) ? tx[0] : 0;
478 [ # # ]: 0 : packet->header[2] = (msg->tx_len > 1) ? tx[1] : 0;
479 : : }
480 : :
481 : 0 : packet->size = sizeof(packet->header) + packet->payload_length;
482 : :
483 : 0 : return 0;
484 : : }
485 : : EXPORT_SYMBOL(mipi_dsi_create_packet);
486 : :
487 : : /**
488 : : * mipi_dsi_shutdown_peripheral() - sends a Shutdown Peripheral command
489 : : * @dsi: DSI peripheral device
490 : : *
491 : : * Return: 0 on success or a negative error code on failure.
492 : : */
493 : 0 : int mipi_dsi_shutdown_peripheral(struct mipi_dsi_device *dsi)
494 : : {
495 : 0 : struct mipi_dsi_msg msg = {
496 : 0 : .channel = dsi->channel,
497 : : .type = MIPI_DSI_SHUTDOWN_PERIPHERAL,
498 : 0 : .tx_buf = (u8 [2]) { 0, 0 },
499 : : .tx_len = 2,
500 : : };
501 : 0 : int ret = mipi_dsi_device_transfer(dsi, &msg);
502 : :
503 : 0 : return (ret < 0) ? ret : 0;
504 : : }
505 : : EXPORT_SYMBOL(mipi_dsi_shutdown_peripheral);
506 : :
507 : : /**
508 : : * mipi_dsi_turn_on_peripheral() - sends a Turn On Peripheral command
509 : : * @dsi: DSI peripheral device
510 : : *
511 : : * Return: 0 on success or a negative error code on failure.
512 : : */
513 : 0 : int mipi_dsi_turn_on_peripheral(struct mipi_dsi_device *dsi)
514 : : {
515 : 0 : struct mipi_dsi_msg msg = {
516 : 0 : .channel = dsi->channel,
517 : : .type = MIPI_DSI_TURN_ON_PERIPHERAL,
518 : 0 : .tx_buf = (u8 [2]) { 0, 0 },
519 : : .tx_len = 2,
520 : : };
521 : 0 : int ret = mipi_dsi_device_transfer(dsi, &msg);
522 : :
523 : 0 : return (ret < 0) ? ret : 0;
524 : : }
525 : : EXPORT_SYMBOL(mipi_dsi_turn_on_peripheral);
526 : :
527 : : /*
528 : : * mipi_dsi_set_maximum_return_packet_size() - specify the maximum size of the
529 : : * the payload in a long packet transmitted from the peripheral back to the
530 : : * host processor
531 : : * @dsi: DSI peripheral device
532 : : * @value: the maximum size of the payload
533 : : *
534 : : * Return: 0 on success or a negative error code on failure.
535 : : */
536 : 0 : int mipi_dsi_set_maximum_return_packet_size(struct mipi_dsi_device *dsi,
537 : : u16 value)
538 : : {
539 : 0 : u8 tx[2] = { value & 0xff, value >> 8 };
540 : 0 : struct mipi_dsi_msg msg = {
541 : 0 : .channel = dsi->channel,
542 : : .type = MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE,
543 : : .tx_len = sizeof(tx),
544 : : .tx_buf = tx,
545 : : };
546 : 0 : int ret = mipi_dsi_device_transfer(dsi, &msg);
547 : :
548 : 0 : return (ret < 0) ? ret : 0;
549 : : }
550 : : EXPORT_SYMBOL(mipi_dsi_set_maximum_return_packet_size);
551 : :
552 : : /**
553 : : * mipi_dsi_compression_mode() - enable/disable DSC on the peripheral
554 : : * @dsi: DSI peripheral device
555 : : * @enable: Whether to enable or disable the DSC
556 : : *
557 : : * Enable or disable Display Stream Compression on the peripheral using the
558 : : * default Picture Parameter Set and VESA DSC 1.1 algorithm.
559 : : *
560 : : * Return: 0 on success or a negative error code on failure.
561 : : */
562 : 0 : ssize_t mipi_dsi_compression_mode(struct mipi_dsi_device *dsi, bool enable)
563 : : {
564 : : /* Note: Needs updating for non-default PPS or algorithm */
565 : 0 : u8 tx[2] = { enable << 0, 0 };
566 : 0 : struct mipi_dsi_msg msg = {
567 : 0 : .channel = dsi->channel,
568 : : .type = MIPI_DSI_COMPRESSION_MODE,
569 : : .tx_len = sizeof(tx),
570 : : .tx_buf = tx,
571 : : };
572 : 0 : int ret = mipi_dsi_device_transfer(dsi, &msg);
573 : :
574 : 0 : return (ret < 0) ? ret : 0;
575 : : }
576 : : EXPORT_SYMBOL(mipi_dsi_compression_mode);
577 : :
578 : : /**
579 : : * mipi_dsi_picture_parameter_set() - transmit the DSC PPS to the peripheral
580 : : * @dsi: DSI peripheral device
581 : : * @pps: VESA DSC 1.1 Picture Parameter Set
582 : : *
583 : : * Transmit the VESA DSC 1.1 Picture Parameter Set to the peripheral.
584 : : *
585 : : * Return: 0 on success or a negative error code on failure.
586 : : */
587 : 0 : ssize_t mipi_dsi_picture_parameter_set(struct mipi_dsi_device *dsi,
588 : : const struct drm_dsc_picture_parameter_set *pps)
589 : : {
590 : 0 : struct mipi_dsi_msg msg = {
591 : 0 : .channel = dsi->channel,
592 : : .type = MIPI_DSI_PICTURE_PARAMETER_SET,
593 : : .tx_len = sizeof(*pps),
594 : : .tx_buf = pps,
595 : : };
596 : 0 : int ret = mipi_dsi_device_transfer(dsi, &msg);
597 : :
598 : 0 : return (ret < 0) ? ret : 0;
599 : : }
600 : : EXPORT_SYMBOL(mipi_dsi_picture_parameter_set);
601 : :
602 : : /**
603 : : * mipi_dsi_generic_write() - transmit data using a generic write packet
604 : : * @dsi: DSI peripheral device
605 : : * @payload: buffer containing the payload
606 : : * @size: size of payload buffer
607 : : *
608 : : * This function will automatically choose the right data type depending on
609 : : * the payload length.
610 : : *
611 : : * Return: The number of bytes transmitted on success or a negative error code
612 : : * on failure.
613 : : */
614 : 0 : ssize_t mipi_dsi_generic_write(struct mipi_dsi_device *dsi, const void *payload,
615 : : size_t size)
616 : : {
617 : 0 : struct mipi_dsi_msg msg = {
618 : 0 : .channel = dsi->channel,
619 : : .tx_buf = payload,
620 : : .tx_len = size
621 : : };
622 : :
623 [ # # # # ]: 0 : switch (size) {
624 : 0 : case 0:
625 : 0 : msg.type = MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM;
626 : 0 : break;
627 : :
628 : 0 : case 1:
629 : 0 : msg.type = MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM;
630 : 0 : break;
631 : :
632 : 0 : case 2:
633 : 0 : msg.type = MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM;
634 : 0 : break;
635 : :
636 : 0 : default:
637 : 0 : msg.type = MIPI_DSI_GENERIC_LONG_WRITE;
638 : 0 : break;
639 : : }
640 : :
641 : 0 : return mipi_dsi_device_transfer(dsi, &msg);
642 : : }
643 : : EXPORT_SYMBOL(mipi_dsi_generic_write);
644 : :
645 : : /**
646 : : * mipi_dsi_generic_read() - receive data using a generic read packet
647 : : * @dsi: DSI peripheral device
648 : : * @params: buffer containing the request parameters
649 : : * @num_params: number of request parameters
650 : : * @data: buffer in which to return the received data
651 : : * @size: size of receive buffer
652 : : *
653 : : * This function will automatically choose the right data type depending on
654 : : * the number of parameters passed in.
655 : : *
656 : : * Return: The number of bytes successfully read or a negative error code on
657 : : * failure.
658 : : */
659 : 0 : ssize_t mipi_dsi_generic_read(struct mipi_dsi_device *dsi, const void *params,
660 : : size_t num_params, void *data, size_t size)
661 : : {
662 : 0 : struct mipi_dsi_msg msg = {
663 : 0 : .channel = dsi->channel,
664 : : .tx_len = num_params,
665 : : .tx_buf = params,
666 : : .rx_len = size,
667 : : .rx_buf = data
668 : : };
669 : :
670 [ # # # # ]: 0 : switch (num_params) {
671 : 0 : case 0:
672 : 0 : msg.type = MIPI_DSI_GENERIC_READ_REQUEST_0_PARAM;
673 : 0 : break;
674 : :
675 : 0 : case 1:
676 : 0 : msg.type = MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM;
677 : 0 : break;
678 : :
679 : 0 : case 2:
680 : 0 : msg.type = MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM;
681 : 0 : break;
682 : :
683 : : default:
684 : : return -EINVAL;
685 : : }
686 : :
687 : 0 : return mipi_dsi_device_transfer(dsi, &msg);
688 : : }
689 : : EXPORT_SYMBOL(mipi_dsi_generic_read);
690 : :
691 : : /**
692 : : * mipi_dsi_dcs_write_buffer() - transmit a DCS command with payload
693 : : * @dsi: DSI peripheral device
694 : : * @data: buffer containing data to be transmitted
695 : : * @len: size of transmission buffer
696 : : *
697 : : * This function will automatically choose the right data type depending on
698 : : * the command payload length.
699 : : *
700 : : * Return: The number of bytes successfully transmitted or a negative error
701 : : * code on failure.
702 : : */
703 : 0 : ssize_t mipi_dsi_dcs_write_buffer(struct mipi_dsi_device *dsi,
704 : : const void *data, size_t len)
705 : : {
706 : 0 : struct mipi_dsi_msg msg = {
707 : 0 : .channel = dsi->channel,
708 : : .tx_buf = data,
709 : : .tx_len = len
710 : : };
711 : :
712 [ # # # # ]: 0 : switch (len) {
713 : : case 0:
714 : : return -EINVAL;
715 : :
716 : 0 : case 1:
717 : 0 : msg.type = MIPI_DSI_DCS_SHORT_WRITE;
718 : 0 : break;
719 : :
720 : 0 : case 2:
721 : 0 : msg.type = MIPI_DSI_DCS_SHORT_WRITE_PARAM;
722 : 0 : break;
723 : :
724 : 0 : default:
725 : 0 : msg.type = MIPI_DSI_DCS_LONG_WRITE;
726 : 0 : break;
727 : : }
728 : :
729 : 0 : return mipi_dsi_device_transfer(dsi, &msg);
730 : : }
731 : : EXPORT_SYMBOL(mipi_dsi_dcs_write_buffer);
732 : :
733 : : /**
734 : : * mipi_dsi_dcs_write() - send DCS write command
735 : : * @dsi: DSI peripheral device
736 : : * @cmd: DCS command
737 : : * @data: buffer containing the command payload
738 : : * @len: command payload length
739 : : *
740 : : * This function will automatically choose the right data type depending on
741 : : * the command payload length.
742 : : *
743 : : * Return: The number of bytes successfully transmitted or a negative error
744 : : * code on failure.
745 : : */
746 : 0 : ssize_t mipi_dsi_dcs_write(struct mipi_dsi_device *dsi, u8 cmd,
747 : : const void *data, size_t len)
748 : : {
749 : 0 : ssize_t err;
750 : 0 : size_t size;
751 : 0 : u8 *tx;
752 : :
753 [ # # ]: 0 : if (len > 0) {
754 : 0 : size = 1 + len;
755 : :
756 [ # # ]: 0 : tx = kmalloc(size, GFP_KERNEL);
757 [ # # ]: 0 : if (!tx)
758 : : return -ENOMEM;
759 : :
760 : : /* concatenate the DCS command byte and the payload */
761 : 0 : tx[0] = cmd;
762 : 0 : memcpy(&tx[1], data, len);
763 : : } else {
764 : : tx = &cmd;
765 : : size = 1;
766 : : }
767 : :
768 : 0 : err = mipi_dsi_dcs_write_buffer(dsi, tx, size);
769 : :
770 [ # # ]: 0 : if (len > 0)
771 : 0 : kfree(tx);
772 : :
773 : : return err;
774 : : }
775 : : EXPORT_SYMBOL(mipi_dsi_dcs_write);
776 : :
777 : : /**
778 : : * mipi_dsi_dcs_read() - send DCS read request command
779 : : * @dsi: DSI peripheral device
780 : : * @cmd: DCS command
781 : : * @data: buffer in which to receive data
782 : : * @len: size of receive buffer
783 : : *
784 : : * Return: The number of bytes read or a negative error code on failure.
785 : : */
786 : 0 : ssize_t mipi_dsi_dcs_read(struct mipi_dsi_device *dsi, u8 cmd, void *data,
787 : : size_t len)
788 : : {
789 : 0 : struct mipi_dsi_msg msg = {
790 : 0 : .channel = dsi->channel,
791 : : .type = MIPI_DSI_DCS_READ,
792 : : .tx_buf = &cmd,
793 : : .tx_len = 1,
794 : : .rx_buf = data,
795 : : .rx_len = len
796 : : };
797 : :
798 : 0 : return mipi_dsi_device_transfer(dsi, &msg);
799 : : }
800 : : EXPORT_SYMBOL(mipi_dsi_dcs_read);
801 : :
802 : : /**
803 : : * mipi_dsi_dcs_nop() - send DCS nop packet
804 : : * @dsi: DSI peripheral device
805 : : *
806 : : * Return: 0 on success or a negative error code on failure.
807 : : */
808 : 0 : int mipi_dsi_dcs_nop(struct mipi_dsi_device *dsi)
809 : : {
810 : 0 : ssize_t err;
811 : :
812 : 0 : err = mipi_dsi_dcs_write(dsi, MIPI_DCS_NOP, NULL, 0);
813 : 0 : if (err < 0)
814 : : return err;
815 : :
816 : : return 0;
817 : : }
818 : : EXPORT_SYMBOL(mipi_dsi_dcs_nop);
819 : :
820 : : /**
821 : : * mipi_dsi_dcs_soft_reset() - perform a software reset of the display module
822 : : * @dsi: DSI peripheral device
823 : : *
824 : : * Return: 0 on success or a negative error code on failure.
825 : : */
826 : 0 : int mipi_dsi_dcs_soft_reset(struct mipi_dsi_device *dsi)
827 : : {
828 : 0 : ssize_t err;
829 : :
830 : 0 : err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SOFT_RESET, NULL, 0);
831 : 0 : if (err < 0)
832 : : return err;
833 : :
834 : : return 0;
835 : : }
836 : : EXPORT_SYMBOL(mipi_dsi_dcs_soft_reset);
837 : :
838 : : /**
839 : : * mipi_dsi_dcs_get_power_mode() - query the display module's current power
840 : : * mode
841 : : * @dsi: DSI peripheral device
842 : : * @mode: return location for the current power mode
843 : : *
844 : : * Return: 0 on success or a negative error code on failure.
845 : : */
846 : 0 : int mipi_dsi_dcs_get_power_mode(struct mipi_dsi_device *dsi, u8 *mode)
847 : : {
848 : 0 : ssize_t err;
849 : :
850 : 0 : err = mipi_dsi_dcs_read(dsi, MIPI_DCS_GET_POWER_MODE, mode,
851 : : sizeof(*mode));
852 [ # # ]: 0 : if (err <= 0) {
853 [ # # ]: 0 : if (err == 0)
854 : 0 : err = -ENODATA;
855 : :
856 : 0 : return err;
857 : : }
858 : :
859 : : return 0;
860 : : }
861 : : EXPORT_SYMBOL(mipi_dsi_dcs_get_power_mode);
862 : :
863 : : /**
864 : : * mipi_dsi_dcs_get_pixel_format() - gets the pixel format for the RGB image
865 : : * data used by the interface
866 : : * @dsi: DSI peripheral device
867 : : * @format: return location for the pixel format
868 : : *
869 : : * Return: 0 on success or a negative error code on failure.
870 : : */
871 : 0 : int mipi_dsi_dcs_get_pixel_format(struct mipi_dsi_device *dsi, u8 *format)
872 : : {
873 : 0 : ssize_t err;
874 : :
875 : 0 : err = mipi_dsi_dcs_read(dsi, MIPI_DCS_GET_PIXEL_FORMAT, format,
876 : : sizeof(*format));
877 [ # # ]: 0 : if (err <= 0) {
878 [ # # ]: 0 : if (err == 0)
879 : 0 : err = -ENODATA;
880 : :
881 : 0 : return err;
882 : : }
883 : :
884 : : return 0;
885 : : }
886 : : EXPORT_SYMBOL(mipi_dsi_dcs_get_pixel_format);
887 : :
888 : : /**
889 : : * mipi_dsi_dcs_enter_sleep_mode() - disable all unnecessary blocks inside the
890 : : * display module except interface communication
891 : : * @dsi: DSI peripheral device
892 : : *
893 : : * Return: 0 on success or a negative error code on failure.
894 : : */
895 : 0 : int mipi_dsi_dcs_enter_sleep_mode(struct mipi_dsi_device *dsi)
896 : : {
897 : 0 : ssize_t err;
898 : :
899 : 0 : err = mipi_dsi_dcs_write(dsi, MIPI_DCS_ENTER_SLEEP_MODE, NULL, 0);
900 : 0 : if (err < 0)
901 : : return err;
902 : :
903 : : return 0;
904 : : }
905 : : EXPORT_SYMBOL(mipi_dsi_dcs_enter_sleep_mode);
906 : :
907 : : /**
908 : : * mipi_dsi_dcs_exit_sleep_mode() - enable all blocks inside the display
909 : : * module
910 : : * @dsi: DSI peripheral device
911 : : *
912 : : * Return: 0 on success or a negative error code on failure.
913 : : */
914 : 0 : int mipi_dsi_dcs_exit_sleep_mode(struct mipi_dsi_device *dsi)
915 : : {
916 : 0 : ssize_t err;
917 : :
918 : 0 : err = mipi_dsi_dcs_write(dsi, MIPI_DCS_EXIT_SLEEP_MODE, NULL, 0);
919 : 0 : if (err < 0)
920 : : return err;
921 : :
922 : : return 0;
923 : : }
924 : : EXPORT_SYMBOL(mipi_dsi_dcs_exit_sleep_mode);
925 : :
926 : : /**
927 : : * mipi_dsi_dcs_set_display_off() - stop displaying the image data on the
928 : : * display device
929 : : * @dsi: DSI peripheral device
930 : : *
931 : : * Return: 0 on success or a negative error code on failure.
932 : : */
933 : 0 : int mipi_dsi_dcs_set_display_off(struct mipi_dsi_device *dsi)
934 : : {
935 : 0 : ssize_t err;
936 : :
937 : 0 : err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_DISPLAY_OFF, NULL, 0);
938 : 0 : if (err < 0)
939 : : return err;
940 : :
941 : : return 0;
942 : : }
943 : : EXPORT_SYMBOL(mipi_dsi_dcs_set_display_off);
944 : :
945 : : /**
946 : : * mipi_dsi_dcs_set_display_on() - start displaying the image data on the
947 : : * display device
948 : : * @dsi: DSI peripheral device
949 : : *
950 : : * Return: 0 on success or a negative error code on failure
951 : : */
952 : 0 : int mipi_dsi_dcs_set_display_on(struct mipi_dsi_device *dsi)
953 : : {
954 : 0 : ssize_t err;
955 : :
956 : 0 : err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_DISPLAY_ON, NULL, 0);
957 : 0 : if (err < 0)
958 : : return err;
959 : :
960 : : return 0;
961 : : }
962 : : EXPORT_SYMBOL(mipi_dsi_dcs_set_display_on);
963 : :
964 : : /**
965 : : * mipi_dsi_dcs_set_column_address() - define the column extent of the frame
966 : : * memory accessed by the host processor
967 : : * @dsi: DSI peripheral device
968 : : * @start: first column of frame memory
969 : : * @end: last column of frame memory
970 : : *
971 : : * Return: 0 on success or a negative error code on failure.
972 : : */
973 : 0 : int mipi_dsi_dcs_set_column_address(struct mipi_dsi_device *dsi, u16 start,
974 : : u16 end)
975 : : {
976 : 0 : u8 payload[4] = { start >> 8, start & 0xff, end >> 8, end & 0xff };
977 : 0 : ssize_t err;
978 : :
979 : 0 : err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_COLUMN_ADDRESS, payload,
980 : : sizeof(payload));
981 : 0 : if (err < 0)
982 : : return err;
983 : :
984 : : return 0;
985 : : }
986 : : EXPORT_SYMBOL(mipi_dsi_dcs_set_column_address);
987 : :
988 : : /**
989 : : * mipi_dsi_dcs_set_page_address() - define the page extent of the frame
990 : : * memory accessed by the host processor
991 : : * @dsi: DSI peripheral device
992 : : * @start: first page of frame memory
993 : : * @end: last page of frame memory
994 : : *
995 : : * Return: 0 on success or a negative error code on failure.
996 : : */
997 : 0 : int mipi_dsi_dcs_set_page_address(struct mipi_dsi_device *dsi, u16 start,
998 : : u16 end)
999 : : {
1000 : 0 : u8 payload[4] = { start >> 8, start & 0xff, end >> 8, end & 0xff };
1001 : 0 : ssize_t err;
1002 : :
1003 : 0 : err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_PAGE_ADDRESS, payload,
1004 : : sizeof(payload));
1005 : 0 : if (err < 0)
1006 : : return err;
1007 : :
1008 : : return 0;
1009 : : }
1010 : : EXPORT_SYMBOL(mipi_dsi_dcs_set_page_address);
1011 : :
1012 : : /**
1013 : : * mipi_dsi_dcs_set_tear_off() - turn off the display module's Tearing Effect
1014 : : * output signal on the TE signal line
1015 : : * @dsi: DSI peripheral device
1016 : : *
1017 : : * Return: 0 on success or a negative error code on failure
1018 : : */
1019 : 0 : int mipi_dsi_dcs_set_tear_off(struct mipi_dsi_device *dsi)
1020 : : {
1021 : 0 : ssize_t err;
1022 : :
1023 : 0 : err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_TEAR_OFF, NULL, 0);
1024 : 0 : if (err < 0)
1025 : : return err;
1026 : :
1027 : : return 0;
1028 : : }
1029 : : EXPORT_SYMBOL(mipi_dsi_dcs_set_tear_off);
1030 : :
1031 : : /**
1032 : : * mipi_dsi_dcs_set_tear_on() - turn on the display module's Tearing Effect
1033 : : * output signal on the TE signal line.
1034 : : * @dsi: DSI peripheral device
1035 : : * @mode: the Tearing Effect Output Line mode
1036 : : *
1037 : : * Return: 0 on success or a negative error code on failure
1038 : : */
1039 : 0 : int mipi_dsi_dcs_set_tear_on(struct mipi_dsi_device *dsi,
1040 : : enum mipi_dsi_dcs_tear_mode mode)
1041 : : {
1042 : 0 : u8 value = mode;
1043 : 0 : ssize_t err;
1044 : :
1045 : 0 : err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_TEAR_ON, &value,
1046 : : sizeof(value));
1047 : 0 : if (err < 0)
1048 : : return err;
1049 : :
1050 : : return 0;
1051 : : }
1052 : : EXPORT_SYMBOL(mipi_dsi_dcs_set_tear_on);
1053 : :
1054 : : /**
1055 : : * mipi_dsi_dcs_set_pixel_format() - sets the pixel format for the RGB image
1056 : : * data used by the interface
1057 : : * @dsi: DSI peripheral device
1058 : : * @format: pixel format
1059 : : *
1060 : : * Return: 0 on success or a negative error code on failure.
1061 : : */
1062 : 0 : int mipi_dsi_dcs_set_pixel_format(struct mipi_dsi_device *dsi, u8 format)
1063 : : {
1064 : 0 : ssize_t err;
1065 : :
1066 : 0 : err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_PIXEL_FORMAT, &format,
1067 : : sizeof(format));
1068 : 0 : if (err < 0)
1069 : : return err;
1070 : :
1071 : : return 0;
1072 : : }
1073 : : EXPORT_SYMBOL(mipi_dsi_dcs_set_pixel_format);
1074 : :
1075 : : /**
1076 : : * mipi_dsi_dcs_set_tear_scanline() - set the scanline to use as trigger for
1077 : : * the Tearing Effect output signal of the display module
1078 : : * @dsi: DSI peripheral device
1079 : : * @scanline: scanline to use as trigger
1080 : : *
1081 : : * Return: 0 on success or a negative error code on failure
1082 : : */
1083 : 0 : int mipi_dsi_dcs_set_tear_scanline(struct mipi_dsi_device *dsi, u16 scanline)
1084 : : {
1085 : 0 : u8 payload[3] = { MIPI_DCS_SET_TEAR_SCANLINE, scanline >> 8,
1086 : : scanline & 0xff };
1087 : 0 : ssize_t err;
1088 : :
1089 : 0 : err = mipi_dsi_generic_write(dsi, payload, sizeof(payload));
1090 : 0 : if (err < 0)
1091 : : return err;
1092 : :
1093 : : return 0;
1094 : : }
1095 : : EXPORT_SYMBOL(mipi_dsi_dcs_set_tear_scanline);
1096 : :
1097 : : /**
1098 : : * mipi_dsi_dcs_set_display_brightness() - sets the brightness value of the
1099 : : * display
1100 : : * @dsi: DSI peripheral device
1101 : : * @brightness: brightness value
1102 : : *
1103 : : * Return: 0 on success or a negative error code on failure.
1104 : : */
1105 : 0 : int mipi_dsi_dcs_set_display_brightness(struct mipi_dsi_device *dsi,
1106 : : u16 brightness)
1107 : : {
1108 : 0 : u8 payload[2] = { brightness & 0xff, brightness >> 8 };
1109 : 0 : ssize_t err;
1110 : :
1111 : 0 : err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_DISPLAY_BRIGHTNESS,
1112 : : payload, sizeof(payload));
1113 : 0 : if (err < 0)
1114 : : return err;
1115 : :
1116 : : return 0;
1117 : : }
1118 : : EXPORT_SYMBOL(mipi_dsi_dcs_set_display_brightness);
1119 : :
1120 : : /**
1121 : : * mipi_dsi_dcs_get_display_brightness() - gets the current brightness value
1122 : : * of the display
1123 : : * @dsi: DSI peripheral device
1124 : : * @brightness: brightness value
1125 : : *
1126 : : * Return: 0 on success or a negative error code on failure.
1127 : : */
1128 : 0 : int mipi_dsi_dcs_get_display_brightness(struct mipi_dsi_device *dsi,
1129 : : u16 *brightness)
1130 : : {
1131 : 0 : ssize_t err;
1132 : :
1133 : 0 : err = mipi_dsi_dcs_read(dsi, MIPI_DCS_GET_DISPLAY_BRIGHTNESS,
1134 : : brightness, sizeof(*brightness));
1135 [ # # ]: 0 : if (err <= 0) {
1136 [ # # ]: 0 : if (err == 0)
1137 : 0 : err = -ENODATA;
1138 : :
1139 : 0 : return err;
1140 : : }
1141 : :
1142 : : return 0;
1143 : : }
1144 : : EXPORT_SYMBOL(mipi_dsi_dcs_get_display_brightness);
1145 : :
1146 : 0 : static int mipi_dsi_drv_probe(struct device *dev)
1147 : : {
1148 : 0 : struct mipi_dsi_driver *drv = to_mipi_dsi_driver(dev->driver);
1149 : 0 : struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev);
1150 : :
1151 : 0 : return drv->probe(dsi);
1152 : : }
1153 : :
1154 : 0 : static int mipi_dsi_drv_remove(struct device *dev)
1155 : : {
1156 : 0 : struct mipi_dsi_driver *drv = to_mipi_dsi_driver(dev->driver);
1157 : 0 : struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev);
1158 : :
1159 : 0 : return drv->remove(dsi);
1160 : : }
1161 : :
1162 : 0 : static void mipi_dsi_drv_shutdown(struct device *dev)
1163 : : {
1164 : 0 : struct mipi_dsi_driver *drv = to_mipi_dsi_driver(dev->driver);
1165 : 0 : struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev);
1166 : :
1167 : 0 : drv->shutdown(dsi);
1168 : 0 : }
1169 : :
1170 : : /**
1171 : : * mipi_dsi_driver_register_full() - register a driver for DSI devices
1172 : : * @drv: DSI driver structure
1173 : : * @owner: owner module
1174 : : *
1175 : : * Return: 0 on success or a negative error code on failure.
1176 : : */
1177 : 0 : int mipi_dsi_driver_register_full(struct mipi_dsi_driver *drv,
1178 : : struct module *owner)
1179 : : {
1180 : 0 : drv->driver.bus = &mipi_dsi_bus_type;
1181 : 0 : drv->driver.owner = owner;
1182 : :
1183 [ # # ]: 0 : if (drv->probe)
1184 : 0 : drv->driver.probe = mipi_dsi_drv_probe;
1185 [ # # ]: 0 : if (drv->remove)
1186 : 0 : drv->driver.remove = mipi_dsi_drv_remove;
1187 [ # # ]: 0 : if (drv->shutdown)
1188 : 0 : drv->driver.shutdown = mipi_dsi_drv_shutdown;
1189 : :
1190 : 0 : return driver_register(&drv->driver);
1191 : : }
1192 : : EXPORT_SYMBOL(mipi_dsi_driver_register_full);
1193 : :
1194 : : /**
1195 : : * mipi_dsi_driver_unregister() - unregister a driver for DSI devices
1196 : : * @drv: DSI driver structure
1197 : : *
1198 : : * Return: 0 on success or a negative error code on failure.
1199 : : */
1200 : 0 : void mipi_dsi_driver_unregister(struct mipi_dsi_driver *drv)
1201 : : {
1202 : 0 : driver_unregister(&drv->driver);
1203 : 0 : }
1204 : : EXPORT_SYMBOL(mipi_dsi_driver_unregister);
1205 : :
1206 : 13 : static int __init mipi_dsi_bus_init(void)
1207 : : {
1208 : 13 : return bus_register(&mipi_dsi_bus_type);
1209 : : }
1210 : : postcore_initcall(mipi_dsi_bus_init);
1211 : :
1212 : : MODULE_AUTHOR("Andrzej Hajda <a.hajda@samsung.com>");
1213 : : MODULE_DESCRIPTION("MIPI DSI Bus");
1214 : : MODULE_LICENSE("GPL and additional rights");
|