1/* $NetBSD: sil164_drv.c,v 1.3 2021/12/18 23:45:27 riastradh Exp $ */ 2 3/* 4 * Copyright (C) 2010 Francisco Jerez. 5 * All Rights Reserved. 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining 8 * a 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, sublicense, 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 17 * portions of the Software. 18 * 19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 22 * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE 23 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 24 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 25 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 * 27 */ 28 29#include <sys/cdefs.h> 30__KERNEL_RCSID(0, "$NetBSD: sil164_drv.c,v 1.3 2021/12/18 23:45:27 riastradh Exp $"); 31 32#include <linux/module.h> 33 34#include <drm/drm_drv.h> 35#include <drm/drm_encoder_slave.h> 36#include <drm/drm_print.h> 37#include <drm/drm_probe_helper.h> 38#include <drm/i2c/sil164.h> 39 40struct sil164_priv { 41 struct sil164_encoder_params config; 42 struct i2c_client *duallink_slave; 43 44 uint8_t saved_state[0x10]; 45 uint8_t saved_slave_state[0x10]; 46}; 47 48#define to_sil164_priv(x) \ 49 ((struct sil164_priv *)to_encoder_slave(x)->slave_priv) 50 51#define sil164_dbg(client, format, ...) do { \ 52 if (drm_debug_enabled(DRM_UT_KMS)) \ 53 dev_printk(KERN_DEBUG, &client->dev, \ 54 "%s: " format, __func__, ## __VA_ARGS__); \ 55 } while (0) 56#define sil164_info(client, format, ...) \ 57 dev_info(&client->dev, format, __VA_ARGS__) 58#define sil164_err(client, format, ...) \ 59 dev_err(&client->dev, format, __VA_ARGS__) 60 61#define SIL164_I2C_ADDR_MASTER 0x38 62#define SIL164_I2C_ADDR_SLAVE 0x39 63 64/* HW register definitions */ 65 66#define SIL164_VENDOR_LO 0x0 67#define SIL164_VENDOR_HI 0x1 68#define SIL164_DEVICE_LO 0x2 69#define SIL164_DEVICE_HI 0x3 70#define SIL164_REVISION 0x4 71#define SIL164_FREQ_MIN 0x6 72#define SIL164_FREQ_MAX 0x7 73#define SIL164_CONTROL0 0x8 74# define SIL164_CONTROL0_POWER_ON 0x01 75# define SIL164_CONTROL0_EDGE_RISING 0x02 76# define SIL164_CONTROL0_INPUT_24BIT 0x04 77# define SIL164_CONTROL0_DUAL_EDGE 0x08 78# define SIL164_CONTROL0_HSYNC_ON 0x10 79# define SIL164_CONTROL0_VSYNC_ON 0x20 80#define SIL164_DETECT 0x9 81# define SIL164_DETECT_INTR_STAT 0x01 82# define SIL164_DETECT_HOTPLUG_STAT 0x02 83# define SIL164_DETECT_RECEIVER_STAT 0x04 84# define SIL164_DETECT_INTR_MODE_RECEIVER 0x00 85# define SIL164_DETECT_INTR_MODE_HOTPLUG 0x08 86# define SIL164_DETECT_OUT_MODE_HIGH 0x00 87# define SIL164_DETECT_OUT_MODE_INTR 0x10 88# define SIL164_DETECT_OUT_MODE_RECEIVER 0x20 89# define SIL164_DETECT_OUT_MODE_HOTPLUG 0x30 90# define SIL164_DETECT_VSWING_STAT 0x80 91#define SIL164_CONTROL1 0xa 92# define SIL164_CONTROL1_DESKEW_ENABLE 0x10 93# define SIL164_CONTROL1_DESKEW_INCR_SHIFT 5 94#define SIL164_GPIO 0xb 95#define SIL164_CONTROL2 0xc 96# define SIL164_CONTROL2_FILTER_ENABLE 0x01 97# define SIL164_CONTROL2_FILTER_SETTING_SHIFT 1 98# define SIL164_CONTROL2_DUALLINK_MASTER 0x40 99# define SIL164_CONTROL2_SYNC_CONT 0x80 100#define SIL164_DUALLINK 0xd 101# define SIL164_DUALLINK_ENABLE 0x10 102# define SIL164_DUALLINK_SKEW_SHIFT 5 103#define SIL164_PLLZONE 0xe 104# define SIL164_PLLZONE_STAT 0x08 105# define SIL164_PLLZONE_FORCE_ON 0x10 106# define SIL164_PLLZONE_FORCE_HIGH 0x20 107 108/* HW access functions */ 109 110static void 111sil164_write(struct i2c_client *client, uint8_t addr, uint8_t val) 112{ 113 uint8_t buf[] = {addr, val}; 114 int ret; 115 116 ret = i2c_master_send(client, buf, ARRAY_SIZE(buf)); 117 if (ret < 0) 118 sil164_err(client, "Error %d writing to subaddress 0x%x\n", 119 ret, addr); 120} 121 122static uint8_t 123sil164_read(struct i2c_client *client, uint8_t addr) 124{ 125 uint8_t val; 126 int ret; 127 128 ret = i2c_master_send(client, &addr, sizeof(addr)); 129 if (ret < 0) 130 goto fail; 131 132 ret = i2c_master_recv(client, &val, sizeof(val)); 133 if (ret < 0) 134 goto fail; 135 136 return val; 137 138fail: 139 sil164_err(client, "Error %d reading from subaddress 0x%x\n", 140 ret, addr); 141 return 0; 142} 143 144static void 145sil164_save_state(struct i2c_client *client, uint8_t *state) 146{ 147 int i; 148 149 for (i = 0x8; i <= 0xe; i++) 150 state[i] = sil164_read(client, i); 151} 152 153static void 154sil164_restore_state(struct i2c_client *client, uint8_t *state) 155{ 156 int i; 157 158 for (i = 0x8; i <= 0xe; i++) 159 sil164_write(client, i, state[i]); 160} 161 162static void 163sil164_set_power_state(struct i2c_client *client, bool on) 164{ 165 uint8_t control0 = sil164_read(client, SIL164_CONTROL0); 166 167 if (on) 168 control0 |= SIL164_CONTROL0_POWER_ON; 169 else 170 control0 &= ~SIL164_CONTROL0_POWER_ON; 171 172 sil164_write(client, SIL164_CONTROL0, control0); 173} 174 175static void 176sil164_init_state(struct i2c_client *client, 177 struct sil164_encoder_params *config, 178 bool duallink) 179{ 180 sil164_write(client, SIL164_CONTROL0, 181 SIL164_CONTROL0_HSYNC_ON | 182 SIL164_CONTROL0_VSYNC_ON | 183 (config->input_edge ? SIL164_CONTROL0_EDGE_RISING : 0) | 184 (config->input_width ? SIL164_CONTROL0_INPUT_24BIT : 0) | 185 (config->input_dual ? SIL164_CONTROL0_DUAL_EDGE : 0)); 186 187 sil164_write(client, SIL164_DETECT, 188 SIL164_DETECT_INTR_STAT | 189 SIL164_DETECT_OUT_MODE_RECEIVER); 190 191 sil164_write(client, SIL164_CONTROL1, 192 (config->input_skew ? SIL164_CONTROL1_DESKEW_ENABLE : 0) | 193 (((config->input_skew + 4) & 0x7) 194 << SIL164_CONTROL1_DESKEW_INCR_SHIFT)); 195 196 sil164_write(client, SIL164_CONTROL2, 197 SIL164_CONTROL2_SYNC_CONT | 198 (config->pll_filter ? 0 : SIL164_CONTROL2_FILTER_ENABLE) | 199 (4 << SIL164_CONTROL2_FILTER_SETTING_SHIFT)); 200 201 sil164_write(client, SIL164_PLLZONE, 0); 202 203 if (duallink) 204 sil164_write(client, SIL164_DUALLINK, 205 SIL164_DUALLINK_ENABLE | 206 (((config->duallink_skew + 4) & 0x7) 207 << SIL164_DUALLINK_SKEW_SHIFT)); 208 else 209 sil164_write(client, SIL164_DUALLINK, 0); 210} 211 212/* DRM encoder functions */ 213 214static void 215sil164_encoder_set_config(struct drm_encoder *encoder, void *params) 216{ 217 struct sil164_priv *priv = to_sil164_priv(encoder); 218 219 priv->config = *(struct sil164_encoder_params *)params; 220} 221 222static void 223sil164_encoder_dpms(struct drm_encoder *encoder, int mode) 224{ 225 struct sil164_priv *priv = to_sil164_priv(encoder); 226 bool on = (mode == DRM_MODE_DPMS_ON); 227 bool duallink = (on && encoder->crtc->mode.clock > 165000); 228 229 sil164_set_power_state(drm_i2c_encoder_get_client(encoder), on); 230 231 if (priv->duallink_slave) 232 sil164_set_power_state(priv->duallink_slave, duallink); 233} 234 235static void 236sil164_encoder_save(struct drm_encoder *encoder) 237{ 238 struct sil164_priv *priv = to_sil164_priv(encoder); 239 240 sil164_save_state(drm_i2c_encoder_get_client(encoder), 241 priv->saved_state); 242 243 if (priv->duallink_slave) 244 sil164_save_state(priv->duallink_slave, 245 priv->saved_slave_state); 246} 247 248static void 249sil164_encoder_restore(struct drm_encoder *encoder) 250{ 251 struct sil164_priv *priv = to_sil164_priv(encoder); 252 253 sil164_restore_state(drm_i2c_encoder_get_client(encoder), 254 priv->saved_state); 255 256 if (priv->duallink_slave) 257 sil164_restore_state(priv->duallink_slave, 258 priv->saved_slave_state); 259} 260 261static int 262sil164_encoder_mode_valid(struct drm_encoder *encoder, 263 struct drm_display_mode *mode) 264{ 265 struct sil164_priv *priv = to_sil164_priv(encoder); 266 267 if (mode->clock < 32000) 268 return MODE_CLOCK_LOW; 269 270 if (mode->clock > 330000 || 271 (mode->clock > 165000 && !priv->duallink_slave)) 272 return MODE_CLOCK_HIGH; 273 274 return MODE_OK; 275} 276 277static void 278sil164_encoder_mode_set(struct drm_encoder *encoder, 279 struct drm_display_mode *mode, 280 struct drm_display_mode *adjusted_mode) 281{ 282 struct sil164_priv *priv = to_sil164_priv(encoder); 283 bool duallink = adjusted_mode->clock > 165000; 284 285 sil164_init_state(drm_i2c_encoder_get_client(encoder), 286 &priv->config, duallink); 287 288 if (priv->duallink_slave) 289 sil164_init_state(priv->duallink_slave, 290 &priv->config, duallink); 291 292 sil164_encoder_dpms(encoder, DRM_MODE_DPMS_ON); 293} 294 295static enum drm_connector_status 296sil164_encoder_detect(struct drm_encoder *encoder, 297 struct drm_connector *connector) 298{ 299 struct i2c_client *client = drm_i2c_encoder_get_client(encoder); 300 301 if (sil164_read(client, SIL164_DETECT) & SIL164_DETECT_HOTPLUG_STAT) 302 return connector_status_connected; 303 else 304 return connector_status_disconnected; 305} 306 307static int 308sil164_encoder_get_modes(struct drm_encoder *encoder, 309 struct drm_connector *connector) 310{ 311 return 0; 312} 313 314static int 315sil164_encoder_create_resources(struct drm_encoder *encoder, 316 struct drm_connector *connector) 317{ 318 return 0; 319} 320 321static int 322sil164_encoder_set_property(struct drm_encoder *encoder, 323 struct drm_connector *connector, 324 struct drm_property *property, 325 uint64_t val) 326{ 327 return 0; 328} 329 330static void 331sil164_encoder_destroy(struct drm_encoder *encoder) 332{ 333 struct sil164_priv *priv = to_sil164_priv(encoder); 334 335 i2c_unregister_device(priv->duallink_slave); 336 337 kfree(priv); 338 drm_i2c_encoder_destroy(encoder); 339} 340 341static const struct drm_encoder_slave_funcs sil164_encoder_funcs = { 342 .set_config = sil164_encoder_set_config, 343 .destroy = sil164_encoder_destroy, 344 .dpms = sil164_encoder_dpms, 345 .save = sil164_encoder_save, 346 .restore = sil164_encoder_restore, 347 .mode_valid = sil164_encoder_mode_valid, 348 .mode_set = sil164_encoder_mode_set, 349 .detect = sil164_encoder_detect, 350 .get_modes = sil164_encoder_get_modes, 351 .create_resources = sil164_encoder_create_resources, 352 .set_property = sil164_encoder_set_property, 353}; 354 355/* I2C driver functions */ 356 357static int 358sil164_probe(struct i2c_client *client, const struct i2c_device_id *id) 359{ 360 int vendor = sil164_read(client, SIL164_VENDOR_HI) << 8 | 361 sil164_read(client, SIL164_VENDOR_LO); 362 int device = sil164_read(client, SIL164_DEVICE_HI) << 8 | 363 sil164_read(client, SIL164_DEVICE_LO); 364 int rev = sil164_read(client, SIL164_REVISION); 365 366 if (vendor != 0x1 || device != 0x6) { 367 sil164_dbg(client, "Unknown device %x:%x.%x\n", 368 vendor, device, rev); 369 return -ENODEV; 370 } 371 372 sil164_info(client, "Detected device %x:%x.%x\n", 373 vendor, device, rev); 374 375 return 0; 376} 377 378static int 379sil164_remove(struct i2c_client *client) 380{ 381 return 0; 382} 383 384static struct i2c_client * 385sil164_detect_slave(struct i2c_client *client) 386{ 387 struct i2c_adapter *adap = client->adapter; 388 struct i2c_msg msg = { 389 .addr = SIL164_I2C_ADDR_SLAVE, 390 .len = 0, 391 }; 392 const struct i2c_board_info info = { 393 I2C_BOARD_INFO("sil164", SIL164_I2C_ADDR_SLAVE) 394 }; 395 396 if (i2c_transfer(adap, &msg, 1) != 1) { 397 sil164_dbg(adap, "No dual-link slave found."); 398 return NULL; 399 } 400 401 return i2c_new_device(adap, &info); 402} 403 404static int 405sil164_encoder_init(struct i2c_client *client, 406 struct drm_device *dev, 407 struct drm_encoder_slave *encoder) 408{ 409 struct sil164_priv *priv; 410 411 priv = kzalloc(sizeof(*priv), GFP_KERNEL); 412 if (!priv) 413 return -ENOMEM; 414 415 encoder->slave_priv = priv; 416 encoder->slave_funcs = &sil164_encoder_funcs; 417 418 priv->duallink_slave = sil164_detect_slave(client); 419 420 return 0; 421} 422 423static const struct i2c_device_id sil164_ids[] = { 424 { "sil164", 0 }, 425 { } 426}; 427MODULE_DEVICE_TABLE(i2c, sil164_ids); 428 429static struct drm_i2c_encoder_driver sil164_driver = { 430 .i2c_driver = { 431 .probe = sil164_probe, 432 .remove = sil164_remove, 433 .driver = { 434 .name = "sil164", 435 }, 436 .id_table = sil164_ids, 437 }, 438 .encoder_init = sil164_encoder_init, 439}; 440 441/* Module initialization */ 442 443static int __init 444sil164_init(void) 445{ 446 return drm_i2c_encoder_register(THIS_MODULE, &sil164_driver); 447} 448 449static void __exit 450sil164_exit(void) 451{ 452 drm_i2c_encoder_unregister(&sil164_driver); 453} 454 455MODULE_AUTHOR("Francisco Jerez <currojerez@riseup.net>"); 456MODULE_DESCRIPTION("Silicon Image sil164 TMDS transmitter driver"); 457MODULE_LICENSE("GPL and additional rights"); 458 459module_init(sil164_init); 460module_exit(sil164_exit); 461