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