1 /* 2 * Copyright (C) 2009 Francisco Jerez. 3 * All Rights Reserved. 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining 6 * a copy of this software and associated documentation files (the 7 * "Software"), to deal in the Software without restriction, including 8 * without limitation the rights to use, copy, modify, merge, publish, 9 * distribute, sublicense, and/or sell copies of the Software, and to 10 * permit persons to whom the Software is furnished to do so, subject to 11 * the following conditions: 12 * 13 * The above copyright notice and this permission notice (including the 14 * next paragraph) shall be included in all copies or substantial 15 * portions of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE 21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 * 25 */ 26 27 #include "drm_encoder_slave.h" 28 29 /** 30 * drm_i2c_encoder_init - Initialize an I2C slave encoder 31 * @dev: DRM device. 32 * @encoder: Encoder to be attached to the I2C device. You aren't 33 * required to have called drm_encoder_init() before. 34 * @adap: I2C adapter that will be used to communicate with 35 * the device. 36 * @info: Information that will be used to create the I2C device. 37 * Required fields are @addr and @type. 38 * 39 * Create an I2C device on the specified bus (the module containing its 40 * driver is transparently loaded) and attach it to the specified 41 * &drm_encoder_slave. The @slave_funcs field will be initialized with 42 * the hooks provided by the slave driver. 43 * 44 * If @info->platform_data is non-NULL it will be used as the initial 45 * slave config. 46 * 47 * Returns 0 on success or a negative errno on failure, in particular, 48 * -ENODEV is returned when no matching driver is found. 49 */ 50 int drm_i2c_encoder_init(struct drm_device *dev, 51 struct drm_encoder_slave *encoder, 52 struct i2c_adapter *adap, 53 const struct i2c_board_info *info) 54 { 55 char modalias[sizeof(I2C_MODULE_PREFIX) 56 + I2C_NAME_SIZE]; 57 struct module *module = NULL; 58 struct i2c_client *client; 59 struct drm_i2c_encoder_driver *encoder_drv; 60 int err = 0; 61 62 snprintf(modalias, sizeof(modalias), 63 "%s%s", I2C_MODULE_PREFIX, info->type); 64 request_module(modalias); 65 66 client = i2c_new_device(adap, info); 67 if (!client) { 68 err = -ENOMEM; 69 goto fail; 70 } 71 72 if (!client->driver) { 73 err = -ENODEV; 74 goto fail_unregister; 75 } 76 77 module = client->driver->driver.owner; 78 if (!try_module_get(module)) { 79 err = -ENODEV; 80 goto fail_unregister; 81 } 82 83 encoder->bus_priv = client; 84 85 encoder_drv = to_drm_i2c_encoder_driver(client->driver); 86 87 err = encoder_drv->encoder_init(client, dev, encoder); 88 if (err) 89 goto fail_unregister; 90 91 if (info->platform_data) 92 encoder->slave_funcs->set_config(&encoder->base, 93 info->platform_data); 94 95 return 0; 96 97 fail_unregister: 98 i2c_unregister_device(client); 99 module_put(module); 100 fail: 101 return err; 102 } 103 EXPORT_SYMBOL(drm_i2c_encoder_init); 104 105 /** 106 * drm_i2c_encoder_destroy - Unregister the I2C device backing an encoder 107 * @drm_encoder: Encoder to be unregistered. 108 * 109 * This should be called from the @destroy method of an I2C slave 110 * encoder driver once I2C access is no longer needed. 111 */ 112 void drm_i2c_encoder_destroy(struct drm_encoder *drm_encoder) 113 { 114 struct drm_encoder_slave *encoder = to_encoder_slave(drm_encoder); 115 struct i2c_client *client = drm_i2c_encoder_get_client(drm_encoder); 116 struct module *module = client->driver->driver.owner; 117 118 i2c_unregister_device(client); 119 encoder->bus_priv = NULL; 120 121 module_put(module); 122 } 123 EXPORT_SYMBOL(drm_i2c_encoder_destroy); 124