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 static int mipi_dsi_device_match(struct device *dev, struct device_driver *drv) 39 { 40 return of_driver_match_device(dev, drv); 41 } 42 43 static const struct dev_pm_ops mipi_dsi_device_pm_ops = { 44 .runtime_suspend = pm_generic_runtime_suspend, 45 .runtime_resume = pm_generic_runtime_resume, 46 .suspend = pm_generic_suspend, 47 .resume = pm_generic_resume, 48 .freeze = pm_generic_freeze, 49 .thaw = pm_generic_thaw, 50 .poweroff = pm_generic_poweroff, 51 .restore = pm_generic_restore, 52 }; 53 54 static struct bus_type mipi_dsi_bus_type = { 55 .name = "mipi-dsi", 56 .match = mipi_dsi_device_match, 57 .pm = &mipi_dsi_device_pm_ops, 58 }; 59 60 static void mipi_dsi_dev_release(struct device *dev) 61 { 62 struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev); 63 64 of_node_put(dev->of_node); 65 kfree(dsi); 66 } 67 68 static const struct device_type mipi_dsi_device_type = { 69 .release = mipi_dsi_dev_release, 70 }; 71 72 static struct mipi_dsi_device *mipi_dsi_device_alloc(struct mipi_dsi_host *host) 73 { 74 struct mipi_dsi_device *dsi; 75 76 dsi = kzalloc(sizeof(*dsi), GFP_KERNEL); 77 if (!dsi) 78 return ERR_PTR(-ENOMEM); 79 80 dsi->host = host; 81 dsi->dev.bus = &mipi_dsi_bus_type; 82 dsi->dev.parent = host->dev; 83 dsi->dev.type = &mipi_dsi_device_type; 84 85 device_initialize(&dsi->dev); 86 87 return dsi; 88 } 89 90 static int mipi_dsi_device_add(struct mipi_dsi_device *dsi) 91 { 92 struct mipi_dsi_host *host = dsi->host; 93 94 dev_set_name(&dsi->dev, "%s.%d", dev_name(host->dev), dsi->channel); 95 96 return device_add(&dsi->dev); 97 } 98 99 static struct mipi_dsi_device * 100 of_mipi_dsi_device_add(struct mipi_dsi_host *host, struct device_node *node) 101 { 102 struct mipi_dsi_device *dsi; 103 struct device *dev = host->dev; 104 int ret; 105 u32 reg; 106 107 ret = of_property_read_u32(node, "reg", ®); 108 if (ret) { 109 dev_err(dev, "device node %s has no valid reg property: %d\n", 110 node->full_name, ret); 111 return ERR_PTR(-EINVAL); 112 } 113 114 if (reg > 3) { 115 dev_err(dev, "device node %s has invalid reg property: %u\n", 116 node->full_name, reg); 117 return ERR_PTR(-EINVAL); 118 } 119 120 dsi = mipi_dsi_device_alloc(host); 121 if (IS_ERR(dsi)) { 122 dev_err(dev, "failed to allocate DSI device %s: %ld\n", 123 node->full_name, PTR_ERR(dsi)); 124 return dsi; 125 } 126 127 dsi->dev.of_node = of_node_get(node); 128 dsi->channel = reg; 129 130 ret = mipi_dsi_device_add(dsi); 131 if (ret) { 132 dev_err(dev, "failed to add DSI device %s: %d\n", 133 node->full_name, ret); 134 kfree(dsi); 135 return ERR_PTR(ret); 136 } 137 138 return dsi; 139 } 140 141 int mipi_dsi_host_register(struct mipi_dsi_host *host) 142 { 143 struct device_node *node; 144 145 for_each_available_child_of_node(host->dev->of_node, node) { 146 /* skip nodes without reg property */ 147 if (!of_find_property(node, "reg", NULL)) 148 continue; 149 of_mipi_dsi_device_add(host, node); 150 } 151 152 return 0; 153 } 154 EXPORT_SYMBOL(mipi_dsi_host_register); 155 156 static int mipi_dsi_remove_device_fn(struct device *dev, void *priv) 157 { 158 struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev); 159 160 device_unregister(&dsi->dev); 161 162 return 0; 163 } 164 165 void mipi_dsi_host_unregister(struct mipi_dsi_host *host) 166 { 167 device_for_each_child(host->dev, NULL, mipi_dsi_remove_device_fn); 168 } 169 EXPORT_SYMBOL(mipi_dsi_host_unregister); 170 171 /** 172 * mipi_dsi_attach - attach a DSI device to its DSI host 173 * @dsi: DSI peripheral 174 */ 175 int mipi_dsi_attach(struct mipi_dsi_device *dsi) 176 { 177 const struct mipi_dsi_host_ops *ops = dsi->host->ops; 178 179 if (!ops || !ops->attach) 180 return -ENOSYS; 181 182 return ops->attach(dsi->host, dsi); 183 } 184 EXPORT_SYMBOL(mipi_dsi_attach); 185 186 /** 187 * mipi_dsi_detach - detach a DSI device from its DSI host 188 * @dsi: DSI peripheral 189 */ 190 int mipi_dsi_detach(struct mipi_dsi_device *dsi) 191 { 192 const struct mipi_dsi_host_ops *ops = dsi->host->ops; 193 194 if (!ops || !ops->detach) 195 return -ENOSYS; 196 197 return ops->detach(dsi->host, dsi); 198 } 199 EXPORT_SYMBOL(mipi_dsi_detach); 200 201 /** 202 * mipi_dsi_dcs_write - send DCS write command 203 * @dsi: DSI device 204 * @channel: virtual channel 205 * @data: pointer to the command followed by parameters 206 * @len: length of @data 207 */ 208 int mipi_dsi_dcs_write(struct mipi_dsi_device *dsi, unsigned int channel, 209 const void *data, size_t len) 210 { 211 const struct mipi_dsi_host_ops *ops = dsi->host->ops; 212 struct mipi_dsi_msg msg = { 213 .channel = channel, 214 .tx_buf = data, 215 .tx_len = len 216 }; 217 218 if (!ops || !ops->transfer) 219 return -ENOSYS; 220 221 switch (len) { 222 case 0: 223 return -EINVAL; 224 case 1: 225 msg.type = MIPI_DSI_DCS_SHORT_WRITE; 226 break; 227 case 2: 228 msg.type = MIPI_DSI_DCS_SHORT_WRITE_PARAM; 229 break; 230 default: 231 msg.type = MIPI_DSI_DCS_LONG_WRITE; 232 break; 233 } 234 235 return ops->transfer(dsi->host, &msg); 236 } 237 EXPORT_SYMBOL(mipi_dsi_dcs_write); 238 239 /** 240 * mipi_dsi_dcs_read - send DCS read request command 241 * @dsi: DSI device 242 * @channel: virtual channel 243 * @cmd: DCS read command 244 * @data: pointer to read buffer 245 * @len: length of @data 246 * 247 * Function returns number of read bytes or error code. 248 */ 249 ssize_t mipi_dsi_dcs_read(struct mipi_dsi_device *dsi, unsigned int channel, 250 u8 cmd, void *data, size_t len) 251 { 252 const struct mipi_dsi_host_ops *ops = dsi->host->ops; 253 struct mipi_dsi_msg msg = { 254 .channel = channel, 255 .type = MIPI_DSI_DCS_READ, 256 .tx_buf = &cmd, 257 .tx_len = 1, 258 .rx_buf = data, 259 .rx_len = len 260 }; 261 262 if (!ops || !ops->transfer) 263 return -ENOSYS; 264 265 return ops->transfer(dsi->host, &msg); 266 } 267 EXPORT_SYMBOL(mipi_dsi_dcs_read); 268 269 static int mipi_dsi_drv_probe(struct device *dev) 270 { 271 struct mipi_dsi_driver *drv = to_mipi_dsi_driver(dev->driver); 272 struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev); 273 274 return drv->probe(dsi); 275 } 276 277 static int mipi_dsi_drv_remove(struct device *dev) 278 { 279 struct mipi_dsi_driver *drv = to_mipi_dsi_driver(dev->driver); 280 struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev); 281 282 return drv->remove(dsi); 283 } 284 285 /** 286 * mipi_dsi_driver_register - register a driver for DSI devices 287 * @drv: DSI driver structure 288 */ 289 int mipi_dsi_driver_register(struct mipi_dsi_driver *drv) 290 { 291 drv->driver.bus = &mipi_dsi_bus_type; 292 if (drv->probe) 293 drv->driver.probe = mipi_dsi_drv_probe; 294 if (drv->remove) 295 drv->driver.remove = mipi_dsi_drv_remove; 296 297 return driver_register(&drv->driver); 298 } 299 EXPORT_SYMBOL(mipi_dsi_driver_register); 300 301 /** 302 * mipi_dsi_driver_unregister - unregister a driver for DSI devices 303 * @drv: DSI driver structure 304 */ 305 void mipi_dsi_driver_unregister(struct mipi_dsi_driver *drv) 306 { 307 driver_unregister(&drv->driver); 308 } 309 EXPORT_SYMBOL(mipi_dsi_driver_unregister); 310 311 static int __init mipi_dsi_bus_init(void) 312 { 313 return bus_register(&mipi_dsi_bus_type); 314 } 315 postcore_initcall(mipi_dsi_bus_init); 316 317 MODULE_AUTHOR("Andrzej Hajda <a.hajda@samsung.com>"); 318 MODULE_DESCRIPTION("MIPI DSI Bus"); 319 MODULE_LICENSE("GPL and additional rights"); 320