1*aee94f86SFrançois Tigeot /* 2*aee94f86SFrançois Tigeot * Copyright (C) 2009 Francisco Jerez. 3*aee94f86SFrançois Tigeot * All Rights Reserved. 4*aee94f86SFrançois Tigeot * 5*aee94f86SFrançois Tigeot * Permission is hereby granted, free of charge, to any person obtaining 6*aee94f86SFrançois Tigeot * a copy of this software and associated documentation files (the 7*aee94f86SFrançois Tigeot * "Software"), to deal in the Software without restriction, including 8*aee94f86SFrançois Tigeot * without limitation the rights to use, copy, modify, merge, publish, 9*aee94f86SFrançois Tigeot * distribute, sublicense, and/or sell copies of the Software, and to 10*aee94f86SFrançois Tigeot * permit persons to whom the Software is furnished to do so, subject to 11*aee94f86SFrançois Tigeot * the following conditions: 12*aee94f86SFrançois Tigeot * 13*aee94f86SFrançois Tigeot * The above copyright notice and this permission notice (including the 14*aee94f86SFrançois Tigeot * next paragraph) shall be included in all copies or substantial 15*aee94f86SFrançois Tigeot * portions of the Software. 16*aee94f86SFrançois Tigeot * 17*aee94f86SFrançois Tigeot * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18*aee94f86SFrançois Tigeot * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19*aee94f86SFrançois Tigeot * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20*aee94f86SFrançois Tigeot * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE 21*aee94f86SFrançois Tigeot * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 22*aee94f86SFrançois Tigeot * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 23*aee94f86SFrançois Tigeot * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24*aee94f86SFrançois Tigeot * 25*aee94f86SFrançois Tigeot */ 26*aee94f86SFrançois Tigeot 27*aee94f86SFrançois Tigeot #include <linux/module.h> 28*aee94f86SFrançois Tigeot 29*aee94f86SFrançois Tigeot #include <drm/drm_encoder_slave.h> 30*aee94f86SFrançois Tigeot 31*aee94f86SFrançois Tigeot #if 0 32*aee94f86SFrançois Tigeot /** 33*aee94f86SFrançois Tigeot * drm_i2c_encoder_init - Initialize an I2C slave encoder 34*aee94f86SFrançois Tigeot * @dev: DRM device. 35*aee94f86SFrançois Tigeot * @encoder: Encoder to be attached to the I2C device. You aren't 36*aee94f86SFrançois Tigeot * required to have called drm_encoder_init() before. 37*aee94f86SFrançois Tigeot * @adap: I2C adapter that will be used to communicate with 38*aee94f86SFrançois Tigeot * the device. 39*aee94f86SFrançois Tigeot * @info: Information that will be used to create the I2C device. 40*aee94f86SFrançois Tigeot * Required fields are @addr and @type. 41*aee94f86SFrançois Tigeot * 42*aee94f86SFrançois Tigeot * Create an I2C device on the specified bus (the module containing its 43*aee94f86SFrançois Tigeot * driver is transparently loaded) and attach it to the specified 44*aee94f86SFrançois Tigeot * &drm_encoder_slave. The @slave_funcs field will be initialized with 45*aee94f86SFrançois Tigeot * the hooks provided by the slave driver. 46*aee94f86SFrançois Tigeot * 47*aee94f86SFrançois Tigeot * If @info->platform_data is non-NULL it will be used as the initial 48*aee94f86SFrançois Tigeot * slave config. 49*aee94f86SFrançois Tigeot * 50*aee94f86SFrançois Tigeot * Returns 0 on success or a negative errno on failure, in particular, 51*aee94f86SFrançois Tigeot * -ENODEV is returned when no matching driver is found. 52*aee94f86SFrançois Tigeot */ 53*aee94f86SFrançois Tigeot int drm_i2c_encoder_init(struct drm_device *dev, 54*aee94f86SFrançois Tigeot struct drm_encoder_slave *encoder, 55*aee94f86SFrançois Tigeot struct i2c_adapter *adap, 56*aee94f86SFrançois Tigeot const struct i2c_board_info *info) 57*aee94f86SFrançois Tigeot { 58*aee94f86SFrançois Tigeot struct module *module = NULL; 59*aee94f86SFrançois Tigeot struct i2c_client *client; 60*aee94f86SFrançois Tigeot struct drm_i2c_encoder_driver *encoder_drv; 61*aee94f86SFrançois Tigeot int err = 0; 62*aee94f86SFrançois Tigeot 63*aee94f86SFrançois Tigeot request_module("%s%s", I2C_MODULE_PREFIX, info->type); 64*aee94f86SFrançois Tigeot 65*aee94f86SFrançois Tigeot client = i2c_new_device(adap, info); 66*aee94f86SFrançois Tigeot if (!client) { 67*aee94f86SFrançois Tigeot err = -ENOMEM; 68*aee94f86SFrançois Tigeot goto fail; 69*aee94f86SFrançois Tigeot } 70*aee94f86SFrançois Tigeot 71*aee94f86SFrançois Tigeot if (!client->dev.driver) { 72*aee94f86SFrançois Tigeot err = -ENODEV; 73*aee94f86SFrançois Tigeot goto fail_unregister; 74*aee94f86SFrançois Tigeot } 75*aee94f86SFrançois Tigeot 76*aee94f86SFrançois Tigeot module = client->dev.driver->owner; 77*aee94f86SFrançois Tigeot if (!try_module_get(module)) { 78*aee94f86SFrançois Tigeot err = -ENODEV; 79*aee94f86SFrançois Tigeot goto fail_unregister; 80*aee94f86SFrançois Tigeot } 81*aee94f86SFrançois Tigeot 82*aee94f86SFrançois Tigeot encoder->bus_priv = client; 83*aee94f86SFrançois Tigeot 84*aee94f86SFrançois Tigeot encoder_drv = to_drm_i2c_encoder_driver(to_i2c_driver(client->dev.driver)); 85*aee94f86SFrançois Tigeot 86*aee94f86SFrançois Tigeot err = encoder_drv->encoder_init(client, dev, encoder); 87*aee94f86SFrançois Tigeot if (err) 88*aee94f86SFrançois Tigeot goto fail_unregister; 89*aee94f86SFrançois Tigeot 90*aee94f86SFrançois Tigeot if (info->platform_data) 91*aee94f86SFrançois Tigeot encoder->slave_funcs->set_config(&encoder->base, 92*aee94f86SFrançois Tigeot info->platform_data); 93*aee94f86SFrançois Tigeot 94*aee94f86SFrançois Tigeot return 0; 95*aee94f86SFrançois Tigeot 96*aee94f86SFrançois Tigeot fail_unregister: 97*aee94f86SFrançois Tigeot i2c_unregister_device(client); 98*aee94f86SFrançois Tigeot module_put(module); 99*aee94f86SFrançois Tigeot fail: 100*aee94f86SFrançois Tigeot return err; 101*aee94f86SFrançois Tigeot } 102*aee94f86SFrançois Tigeot EXPORT_SYMBOL(drm_i2c_encoder_init); 103*aee94f86SFrançois Tigeot 104*aee94f86SFrançois Tigeot /** 105*aee94f86SFrançois Tigeot * drm_i2c_encoder_destroy - Unregister the I2C device backing an encoder 106*aee94f86SFrançois Tigeot * @drm_encoder: Encoder to be unregistered. 107*aee94f86SFrançois Tigeot * 108*aee94f86SFrançois Tigeot * This should be called from the @destroy method of an I2C slave 109*aee94f86SFrançois Tigeot * encoder driver once I2C access is no longer needed. 110*aee94f86SFrançois Tigeot */ 111*aee94f86SFrançois Tigeot void drm_i2c_encoder_destroy(struct drm_encoder *drm_encoder) 112*aee94f86SFrançois Tigeot { 113*aee94f86SFrançois Tigeot struct drm_encoder_slave *encoder = to_encoder_slave(drm_encoder); 114*aee94f86SFrançois Tigeot struct i2c_client *client = drm_i2c_encoder_get_client(drm_encoder); 115*aee94f86SFrançois Tigeot struct module *module = client->dev.driver->owner; 116*aee94f86SFrançois Tigeot 117*aee94f86SFrançois Tigeot i2c_unregister_device(client); 118*aee94f86SFrançois Tigeot encoder->bus_priv = NULL; 119*aee94f86SFrançois Tigeot 120*aee94f86SFrançois Tigeot module_put(module); 121*aee94f86SFrançois Tigeot } 122*aee94f86SFrançois Tigeot EXPORT_SYMBOL(drm_i2c_encoder_destroy); 123*aee94f86SFrançois Tigeot #endif 124*aee94f86SFrançois Tigeot 125*aee94f86SFrançois Tigeot /* 126*aee94f86SFrançois Tigeot * Wrapper fxns which can be plugged in to drm_encoder_helper_funcs: 127*aee94f86SFrançois Tigeot */ 128*aee94f86SFrançois Tigeot 129*aee94f86SFrançois Tigeot static inline const struct drm_encoder_slave_funcs * 130*aee94f86SFrançois Tigeot get_slave_funcs(struct drm_encoder *enc) 131*aee94f86SFrançois Tigeot { 132*aee94f86SFrançois Tigeot return to_encoder_slave(enc)->slave_funcs; 133*aee94f86SFrançois Tigeot } 134*aee94f86SFrançois Tigeot 135*aee94f86SFrançois Tigeot void drm_i2c_encoder_dpms(struct drm_encoder *encoder, int mode) 136*aee94f86SFrançois Tigeot { 137*aee94f86SFrançois Tigeot get_slave_funcs(encoder)->dpms(encoder, mode); 138*aee94f86SFrançois Tigeot } 139*aee94f86SFrançois Tigeot EXPORT_SYMBOL(drm_i2c_encoder_dpms); 140*aee94f86SFrançois Tigeot 141*aee94f86SFrançois Tigeot bool drm_i2c_encoder_mode_fixup(struct drm_encoder *encoder, 142*aee94f86SFrançois Tigeot const struct drm_display_mode *mode, 143*aee94f86SFrançois Tigeot struct drm_display_mode *adjusted_mode) 144*aee94f86SFrançois Tigeot { 145*aee94f86SFrançois Tigeot return get_slave_funcs(encoder)->mode_fixup(encoder, mode, adjusted_mode); 146*aee94f86SFrançois Tigeot } 147*aee94f86SFrançois Tigeot EXPORT_SYMBOL(drm_i2c_encoder_mode_fixup); 148*aee94f86SFrançois Tigeot 149*aee94f86SFrançois Tigeot void drm_i2c_encoder_prepare(struct drm_encoder *encoder) 150*aee94f86SFrançois Tigeot { 151*aee94f86SFrançois Tigeot drm_i2c_encoder_dpms(encoder, DRM_MODE_DPMS_OFF); 152*aee94f86SFrançois Tigeot } 153*aee94f86SFrançois Tigeot EXPORT_SYMBOL(drm_i2c_encoder_prepare); 154*aee94f86SFrançois Tigeot 155*aee94f86SFrançois Tigeot void drm_i2c_encoder_commit(struct drm_encoder *encoder) 156*aee94f86SFrançois Tigeot { 157*aee94f86SFrançois Tigeot drm_i2c_encoder_dpms(encoder, DRM_MODE_DPMS_ON); 158*aee94f86SFrançois Tigeot } 159*aee94f86SFrançois Tigeot EXPORT_SYMBOL(drm_i2c_encoder_commit); 160*aee94f86SFrançois Tigeot 161*aee94f86SFrançois Tigeot void drm_i2c_encoder_mode_set(struct drm_encoder *encoder, 162*aee94f86SFrançois Tigeot struct drm_display_mode *mode, 163*aee94f86SFrançois Tigeot struct drm_display_mode *adjusted_mode) 164*aee94f86SFrançois Tigeot { 165*aee94f86SFrançois Tigeot get_slave_funcs(encoder)->mode_set(encoder, mode, adjusted_mode); 166*aee94f86SFrançois Tigeot } 167*aee94f86SFrançois Tigeot EXPORT_SYMBOL(drm_i2c_encoder_mode_set); 168*aee94f86SFrançois Tigeot 169*aee94f86SFrançois Tigeot enum drm_connector_status drm_i2c_encoder_detect(struct drm_encoder *encoder, 170*aee94f86SFrançois Tigeot struct drm_connector *connector) 171*aee94f86SFrançois Tigeot { 172*aee94f86SFrançois Tigeot return get_slave_funcs(encoder)->detect(encoder, connector); 173*aee94f86SFrançois Tigeot } 174*aee94f86SFrançois Tigeot EXPORT_SYMBOL(drm_i2c_encoder_detect); 175*aee94f86SFrançois Tigeot 176*aee94f86SFrançois Tigeot void drm_i2c_encoder_save(struct drm_encoder *encoder) 177*aee94f86SFrançois Tigeot { 178*aee94f86SFrançois Tigeot get_slave_funcs(encoder)->save(encoder); 179*aee94f86SFrançois Tigeot } 180*aee94f86SFrançois Tigeot EXPORT_SYMBOL(drm_i2c_encoder_save); 181*aee94f86SFrançois Tigeot 182*aee94f86SFrançois Tigeot void drm_i2c_encoder_restore(struct drm_encoder *encoder) 183*aee94f86SFrançois Tigeot { 184*aee94f86SFrançois Tigeot get_slave_funcs(encoder)->restore(encoder); 185*aee94f86SFrançois Tigeot } 186*aee94f86SFrançois Tigeot EXPORT_SYMBOL(drm_i2c_encoder_restore); 187