Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * DRM driver for Solomon SSD130x OLED displays
   4 *
   5 * Copyright 2022 Red Hat Inc.
   6 * Author: Javier Martinez Canillas <javierm@redhat.com>
   7 *
   8 * Based on drivers/video/fbdev/ssd1307fb.c
   9 * Copyright 2012 Free Electrons
  10 */
  11
  12#include <linux/backlight.h>
  13#include <linux/bitfield.h>
  14#include <linux/bits.h>
  15#include <linux/delay.h>
  16#include <linux/gpio/consumer.h>
  17#include <linux/property.h>
  18#include <linux/pwm.h>
  19#include <linux/regulator/consumer.h>
  20
  21#include <drm/drm_atomic.h>
  22#include <drm/drm_atomic_helper.h>
  23#include <drm/drm_crtc_helper.h>
  24#include <drm/drm_damage_helper.h>
  25#include <drm/drm_edid.h>
  26#include <drm/drm_fbdev_generic.h>
  27#include <drm/drm_format_helper.h>
  28#include <drm/drm_framebuffer.h>
  29#include <drm/drm_gem_atomic_helper.h>
  30#include <drm/drm_gem_framebuffer_helper.h>
  31#include <drm/drm_gem_shmem_helper.h>
  32#include <drm/drm_managed.h>
  33#include <drm/drm_modes.h>
  34#include <drm/drm_rect.h>
  35#include <drm/drm_probe_helper.h>
  36
  37#include "ssd130x.h"
  38
  39#define DRIVER_NAME	"ssd130x"
  40#define DRIVER_DESC	"DRM driver for Solomon SSD130x OLED displays"
  41#define DRIVER_DATE	"20220131"
  42#define DRIVER_MAJOR	1
  43#define DRIVER_MINOR	0
  44
  45#define SSD130X_PAGE_COL_START_LOW		0x00
  46#define SSD130X_PAGE_COL_START_HIGH		0x10
  47#define SSD130X_SET_ADDRESS_MODE		0x20
  48#define SSD130X_SET_COL_RANGE			0x21
  49#define SSD130X_SET_PAGE_RANGE			0x22
  50#define SSD130X_CONTRAST			0x81
  51#define SSD130X_SET_LOOKUP_TABLE		0x91
  52#define SSD130X_CHARGE_PUMP			0x8d
  53#define SSD130X_SET_SEG_REMAP			0xa0
  54#define SSD130X_DISPLAY_OFF			0xae
  55#define SSD130X_SET_MULTIPLEX_RATIO		0xa8
  56#define SSD130X_DISPLAY_ON			0xaf
  57#define SSD130X_START_PAGE_ADDRESS		0xb0
  58#define SSD130X_SET_COM_SCAN_DIR		0xc0
  59#define SSD130X_SET_DISPLAY_OFFSET		0xd3
  60#define SSD130X_SET_CLOCK_FREQ			0xd5
  61#define SSD130X_SET_AREA_COLOR_MODE		0xd8
  62#define SSD130X_SET_PRECHARGE_PERIOD		0xd9
  63#define SSD130X_SET_COM_PINS_CONFIG		0xda
  64#define SSD130X_SET_VCOMH			0xdb
  65
  66#define SSD130X_PAGE_COL_START_MASK		GENMASK(3, 0)
  67#define SSD130X_PAGE_COL_START_HIGH_SET(val)	FIELD_PREP(SSD130X_PAGE_COL_START_MASK, (val) >> 4)
  68#define SSD130X_PAGE_COL_START_LOW_SET(val)	FIELD_PREP(SSD130X_PAGE_COL_START_MASK, (val))
  69#define SSD130X_START_PAGE_ADDRESS_MASK		GENMASK(2, 0)
  70#define SSD130X_START_PAGE_ADDRESS_SET(val)	FIELD_PREP(SSD130X_START_PAGE_ADDRESS_MASK, (val))
  71#define SSD130X_SET_SEG_REMAP_MASK		GENMASK(0, 0)
  72#define SSD130X_SET_SEG_REMAP_SET(val)		FIELD_PREP(SSD130X_SET_SEG_REMAP_MASK, (val))
  73#define SSD130X_SET_COM_SCAN_DIR_MASK		GENMASK(3, 3)
  74#define SSD130X_SET_COM_SCAN_DIR_SET(val)	FIELD_PREP(SSD130X_SET_COM_SCAN_DIR_MASK, (val))
  75#define SSD130X_SET_CLOCK_DIV_MASK		GENMASK(3, 0)
  76#define SSD130X_SET_CLOCK_DIV_SET(val)		FIELD_PREP(SSD130X_SET_CLOCK_DIV_MASK, (val))
  77#define SSD130X_SET_CLOCK_FREQ_MASK		GENMASK(7, 4)
  78#define SSD130X_SET_CLOCK_FREQ_SET(val)		FIELD_PREP(SSD130X_SET_CLOCK_FREQ_MASK, (val))
  79#define SSD130X_SET_PRECHARGE_PERIOD1_MASK	GENMASK(3, 0)
  80#define SSD130X_SET_PRECHARGE_PERIOD1_SET(val)	FIELD_PREP(SSD130X_SET_PRECHARGE_PERIOD1_MASK, (val))
  81#define SSD130X_SET_PRECHARGE_PERIOD2_MASK	GENMASK(7, 4)
  82#define SSD130X_SET_PRECHARGE_PERIOD2_SET(val)	FIELD_PREP(SSD130X_SET_PRECHARGE_PERIOD2_MASK, (val))
  83#define SSD130X_SET_COM_PINS_CONFIG1_MASK	GENMASK(4, 4)
  84#define SSD130X_SET_COM_PINS_CONFIG1_SET(val)	FIELD_PREP(SSD130X_SET_COM_PINS_CONFIG1_MASK, !(val))
  85#define SSD130X_SET_COM_PINS_CONFIG2_MASK	GENMASK(5, 5)
  86#define SSD130X_SET_COM_PINS_CONFIG2_SET(val)	FIELD_PREP(SSD130X_SET_COM_PINS_CONFIG2_MASK, (val))
  87
  88#define SSD130X_SET_ADDRESS_MODE_HORIZONTAL	0x00
  89#define SSD130X_SET_ADDRESS_MODE_VERTICAL	0x01
  90#define SSD130X_SET_ADDRESS_MODE_PAGE		0x02
  91
  92#define SSD130X_SET_AREA_COLOR_MODE_ENABLE	0x1e
  93#define SSD130X_SET_AREA_COLOR_MODE_LOW_POWER	0x05
  94
  95#define MAX_CONTRAST 255
  96
  97const struct ssd130x_deviceinfo ssd130x_variants[] = {
  98	[SH1106_ID] = {
  99		.default_vcomh = 0x40,
 100		.default_dclk_div = 1,
 101		.default_dclk_frq = 5,
 102		.page_mode_only = 1,
 103	},
 104	[SSD1305_ID] = {
 105		.default_vcomh = 0x34,
 106		.default_dclk_div = 1,
 107		.default_dclk_frq = 7,
 108	},
 109	[SSD1306_ID] = {
 110		.default_vcomh = 0x20,
 111		.default_dclk_div = 1,
 112		.default_dclk_frq = 8,
 113		.need_chargepump = 1,
 114	},
 115	[SSD1307_ID] = {
 116		.default_vcomh = 0x20,
 117		.default_dclk_div = 2,
 118		.default_dclk_frq = 12,
 119		.need_pwm = 1,
 120	},
 121	[SSD1309_ID] = {
 122		.default_vcomh = 0x34,
 123		.default_dclk_div = 1,
 124		.default_dclk_frq = 10,
 125	}
 126};
 127EXPORT_SYMBOL_NS_GPL(ssd130x_variants, DRM_SSD130X);
 128
 129static inline struct ssd130x_device *drm_to_ssd130x(struct drm_device *drm)
 130{
 131	return container_of(drm, struct ssd130x_device, drm);
 132}
 133
 134/*
 135 * Helper to write data (SSD130X_DATA) to the device.
 136 */
 137static int ssd130x_write_data(struct ssd130x_device *ssd130x, u8 *values, int count)
 138{
 139	return regmap_bulk_write(ssd130x->regmap, SSD130X_DATA, values, count);
 140}
 141
 142/*
 143 * Helper to write command (SSD130X_COMMAND). The fist variadic argument
 144 * is the command to write and the following are the command options.
 145 *
 146 * Note that the ssd130x protocol requires each command and option to be
 147 * written as a SSD130X_COMMAND device register value. That is why a call
 148 * to regmap_write(..., SSD130X_COMMAND, ...) is done for each argument.
 149 */
 150static int ssd130x_write_cmd(struct ssd130x_device *ssd130x, int count,
 151			     /* u8 cmd, u8 option, ... */...)
 152{
 153	va_list ap;
 154	u8 value;
 155	int ret;
 156
 157	va_start(ap, count);
 158
 159	do {
 160		value = va_arg(ap, int);
 161		ret = regmap_write(ssd130x->regmap, SSD130X_COMMAND, value);
 162		if (ret)
 163			goto out_end;
 164	} while (--count);
 165
 166out_end:
 167	va_end(ap);
 168
 169	return ret;
 170}
 171
 172/* Set address range for horizontal/vertical addressing modes */
 173static int ssd130x_set_col_range(struct ssd130x_device *ssd130x,
 174				 u8 col_start, u8 cols)
 175{
 176	u8 col_end = col_start + cols - 1;
 177	int ret;
 178
 179	if (col_start == ssd130x->col_start && col_end == ssd130x->col_end)
 180		return 0;
 181
 182	ret = ssd130x_write_cmd(ssd130x, 3, SSD130X_SET_COL_RANGE, col_start, col_end);
 183	if (ret < 0)
 184		return ret;
 185
 186	ssd130x->col_start = col_start;
 187	ssd130x->col_end = col_end;
 188	return 0;
 189}
 190
 191static int ssd130x_set_page_range(struct ssd130x_device *ssd130x,
 192				  u8 page_start, u8 pages)
 193{
 194	u8 page_end = page_start + pages - 1;
 195	int ret;
 196
 197	if (page_start == ssd130x->page_start && page_end == ssd130x->page_end)
 198		return 0;
 199
 200	ret = ssd130x_write_cmd(ssd130x, 3, SSD130X_SET_PAGE_RANGE, page_start, page_end);
 201	if (ret < 0)
 202		return ret;
 203
 204	ssd130x->page_start = page_start;
 205	ssd130x->page_end = page_end;
 206	return 0;
 207}
 208
 209/* Set page and column start address for page addressing mode */
 210static int ssd130x_set_page_pos(struct ssd130x_device *ssd130x,
 211				u8 page_start, u8 col_start)
 212{
 213	int ret;
 214	u32 page, col_low, col_high;
 215
 216	page = SSD130X_START_PAGE_ADDRESS |
 217	       SSD130X_START_PAGE_ADDRESS_SET(page_start);
 218	col_low = SSD130X_PAGE_COL_START_LOW |
 219		  SSD130X_PAGE_COL_START_LOW_SET(col_start);
 220	col_high = SSD130X_PAGE_COL_START_HIGH |
 221		   SSD130X_PAGE_COL_START_HIGH_SET(col_start);
 222	ret = ssd130x_write_cmd(ssd130x, 3, page, col_low, col_high);
 223	if (ret < 0)
 224		return ret;
 225
 226	return 0;
 227}
 228
 229static int ssd130x_pwm_enable(struct ssd130x_device *ssd130x)
 230{
 231	struct device *dev = ssd130x->dev;
 232	struct pwm_state pwmstate;
 233
 234	ssd130x->pwm = pwm_get(dev, NULL);
 235	if (IS_ERR(ssd130x->pwm)) {
 236		dev_err(dev, "Could not get PWM from firmware description!\n");
 237		return PTR_ERR(ssd130x->pwm);
 238	}
 239
 240	pwm_init_state(ssd130x->pwm, &pwmstate);
 241	pwm_set_relative_duty_cycle(&pwmstate, 50, 100);
 242	pwm_apply_state(ssd130x->pwm, &pwmstate);
 243
 244	/* Enable the PWM */
 245	pwm_enable(ssd130x->pwm);
 246
 247	dev_dbg(dev, "Using PWM%d with a %lluns period.\n",
 248		ssd130x->pwm->pwm, pwm_get_period(ssd130x->pwm));
 249
 250	return 0;
 251}
 252
 253static void ssd130x_reset(struct ssd130x_device *ssd130x)
 254{
 255	if (!ssd130x->reset)
 256		return;
 257
 258	/* Reset the screen */
 259	gpiod_set_value_cansleep(ssd130x->reset, 1);
 260	udelay(4);
 261	gpiod_set_value_cansleep(ssd130x->reset, 0);
 262	udelay(4);
 263}
 264
 265static int ssd130x_power_on(struct ssd130x_device *ssd130x)
 266{
 267	struct device *dev = ssd130x->dev;
 268	int ret;
 269
 270	ssd130x_reset(ssd130x);
 271
 272	ret = regulator_enable(ssd130x->vcc_reg);
 273	if (ret) {
 274		dev_err(dev, "Failed to enable VCC: %d\n", ret);
 275		return ret;
 276	}
 277
 278	if (ssd130x->device_info->need_pwm) {
 279		ret = ssd130x_pwm_enable(ssd130x);
 280		if (ret) {
 281			dev_err(dev, "Failed to enable PWM: %d\n", ret);
 282			regulator_disable(ssd130x->vcc_reg);
 283			return ret;
 284		}
 285	}
 286
 287	return 0;
 288}
 289
 290static void ssd130x_power_off(struct ssd130x_device *ssd130x)
 291{
 292	pwm_disable(ssd130x->pwm);
 293	pwm_put(ssd130x->pwm);
 294
 295	regulator_disable(ssd130x->vcc_reg);
 296}
 297
 298static int ssd130x_init(struct ssd130x_device *ssd130x)
 299{
 300	u32 precharge, dclk, com_invdir, compins, chargepump, seg_remap;
 301	int ret;
 302
 303	/* Set initial contrast */
 304	ret = ssd130x_write_cmd(ssd130x, 2, SSD130X_CONTRAST, ssd130x->contrast);
 305	if (ret < 0)
 306		return ret;
 307
 308	/* Set segment re-map */
 309	seg_remap = (SSD130X_SET_SEG_REMAP |
 310		     SSD130X_SET_SEG_REMAP_SET(ssd130x->seg_remap));
 311	ret = ssd130x_write_cmd(ssd130x, 1, seg_remap);
 312	if (ret < 0)
 313		return ret;
 314
 315	/* Set COM direction */
 316	com_invdir = (SSD130X_SET_COM_SCAN_DIR |
 317		      SSD130X_SET_COM_SCAN_DIR_SET(ssd130x->com_invdir));
 318	ret = ssd130x_write_cmd(ssd130x,  1, com_invdir);
 319	if (ret < 0)
 320		return ret;
 321
 322	/* Set multiplex ratio value */
 323	ret = ssd130x_write_cmd(ssd130x, 2, SSD130X_SET_MULTIPLEX_RATIO, ssd130x->height - 1);
 324	if (ret < 0)
 325		return ret;
 326
 327	/* set display offset value */
 328	ret = ssd130x_write_cmd(ssd130x, 2, SSD130X_SET_DISPLAY_OFFSET, ssd130x->com_offset);
 329	if (ret < 0)
 330		return ret;
 331
 332	/* Set clock frequency */
 333	dclk = (SSD130X_SET_CLOCK_DIV_SET(ssd130x->dclk_div - 1) |
 334		SSD130X_SET_CLOCK_FREQ_SET(ssd130x->dclk_frq));
 335	ret = ssd130x_write_cmd(ssd130x, 2, SSD130X_SET_CLOCK_FREQ, dclk);
 336	if (ret < 0)
 337		return ret;
 338
 339	/* Set Area Color Mode ON/OFF & Low Power Display Mode */
 340	if (ssd130x->area_color_enable || ssd130x->low_power) {
 341		u32 mode = 0;
 342
 343		if (ssd130x->area_color_enable)
 344			mode |= SSD130X_SET_AREA_COLOR_MODE_ENABLE;
 345
 346		if (ssd130x->low_power)
 347			mode |= SSD130X_SET_AREA_COLOR_MODE_LOW_POWER;
 348
 349		ret = ssd130x_write_cmd(ssd130x, 2, SSD130X_SET_AREA_COLOR_MODE, mode);
 350		if (ret < 0)
 351			return ret;
 352	}
 353
 354	/* Set precharge period in number of ticks from the internal clock */
 355	precharge = (SSD130X_SET_PRECHARGE_PERIOD1_SET(ssd130x->prechargep1) |
 356		     SSD130X_SET_PRECHARGE_PERIOD2_SET(ssd130x->prechargep2));
 357	ret = ssd130x_write_cmd(ssd130x, 2, SSD130X_SET_PRECHARGE_PERIOD, precharge);
 358	if (ret < 0)
 359		return ret;
 360
 361	/* Set COM pins configuration */
 362	compins = BIT(1);
 363	compins |= (SSD130X_SET_COM_PINS_CONFIG1_SET(ssd130x->com_seq) |
 364		    SSD130X_SET_COM_PINS_CONFIG2_SET(ssd130x->com_lrremap));
 365	ret = ssd130x_write_cmd(ssd130x, 2, SSD130X_SET_COM_PINS_CONFIG, compins);
 366	if (ret < 0)
 367		return ret;
 368
 369	/* Set VCOMH */
 370	ret = ssd130x_write_cmd(ssd130x, 2, SSD130X_SET_VCOMH, ssd130x->vcomh);
 371	if (ret < 0)
 372		return ret;
 373
 374	/* Turn on the DC-DC Charge Pump */
 375	chargepump = BIT(4);
 376
 377	if (ssd130x->device_info->need_chargepump)
 378		chargepump |= BIT(2);
 379
 380	ret = ssd130x_write_cmd(ssd130x, 2, SSD130X_CHARGE_PUMP, chargepump);
 381	if (ret < 0)
 382		return ret;
 383
 384	/* Set lookup table */
 385	if (ssd130x->lookup_table_set) {
 386		int i;
 387
 388		ret = ssd130x_write_cmd(ssd130x, 1, SSD130X_SET_LOOKUP_TABLE);
 389		if (ret < 0)
 390			return ret;
 391
 392		for (i = 0; i < ARRAY_SIZE(ssd130x->lookup_table); i++) {
 393			u8 val = ssd130x->lookup_table[i];
 394
 395			if (val < 31 || val > 63)
 396				dev_warn(ssd130x->dev,
 397					 "lookup table index %d value out of range 31 <= %d <= 63\n",
 398					 i, val);
 399			ret = ssd130x_write_cmd(ssd130x, 1, val);
 400			if (ret < 0)
 401				return ret;
 402		}
 403	}
 404
 405	/* Switch to page addressing mode */
 406	if (ssd130x->page_address_mode)
 407		return ssd130x_write_cmd(ssd130x, 2, SSD130X_SET_ADDRESS_MODE,
 408					 SSD130X_SET_ADDRESS_MODE_PAGE);
 409
 410	/* Switch to horizontal addressing mode */
 411	return ssd130x_write_cmd(ssd130x, 2, SSD130X_SET_ADDRESS_MODE,
 412				 SSD130X_SET_ADDRESS_MODE_HORIZONTAL);
 413}
 414
 415static int ssd130x_update_rect(struct ssd130x_device *ssd130x, u8 *buf,
 416			       struct drm_rect *rect)
 417{
 418	unsigned int x = rect->x1;
 419	unsigned int y = rect->y1;
 420	unsigned int width = drm_rect_width(rect);
 421	unsigned int height = drm_rect_height(rect);
 422	unsigned int line_length = DIV_ROUND_UP(width, 8);
 423	unsigned int pages = DIV_ROUND_UP(height, 8);
 424	struct drm_device *drm = &ssd130x->drm;
 425	u32 array_idx = 0;
 426	int ret, i, j, k;
 427	u8 *data_array = NULL;
 428
 429	drm_WARN_ONCE(drm, y % 8 != 0, "y must be aligned to screen page\n");
 430
 431	data_array = kcalloc(width, pages, GFP_KERNEL);
 432	if (!data_array)
 433		return -ENOMEM;
 434
 435	/*
 436	 * The screen is divided in pages, each having a height of 8
 437	 * pixels, and the width of the screen. When sending a byte of
 438	 * data to the controller, it gives the 8 bits for the current
 439	 * column. I.e, the first byte are the 8 bits of the first
 440	 * column, then the 8 bits for the second column, etc.
 441	 *
 442	 *
 443	 * Representation of the screen, assuming it is 5 bits
 444	 * wide. Each letter-number combination is a bit that controls
 445	 * one pixel.
 446	 *
 447	 * A0 A1 A2 A3 A4
 448	 * B0 B1 B2 B3 B4
 449	 * C0 C1 C2 C3 C4
 450	 * D0 D1 D2 D3 D4
 451	 * E0 E1 E2 E3 E4
 452	 * F0 F1 F2 F3 F4
 453	 * G0 G1 G2 G3 G4
 454	 * H0 H1 H2 H3 H4
 455	 *
 456	 * If you want to update this screen, you need to send 5 bytes:
 457	 *  (1) A0 B0 C0 D0 E0 F0 G0 H0
 458	 *  (2) A1 B1 C1 D1 E1 F1 G1 H1
 459	 *  (3) A2 B2 C2 D2 E2 F2 G2 H2
 460	 *  (4) A3 B3 C3 D3 E3 F3 G3 H3
 461	 *  (5) A4 B4 C4 D4 E4 F4 G4 H4
 462	 */
 463
 464	if (!ssd130x->page_address_mode) {
 465		/* Set address range for horizontal addressing mode */
 466		ret = ssd130x_set_col_range(ssd130x, ssd130x->col_offset + x, width);
 467		if (ret < 0)
 468			goto out_free;
 469
 470		ret = ssd130x_set_page_range(ssd130x, ssd130x->page_offset + y / 8, pages);
 471		if (ret < 0)
 472			goto out_free;
 473	}
 474
 475	for (i = 0; i < pages; i++) {
 476		int m = 8;
 477
 478		/* Last page may be partial */
 479		if (8 * (y / 8 + i + 1) > ssd130x->height)
 480			m = ssd130x->height % 8;
 481		for (j = 0; j < width; j++) {
 482			u8 data = 0;
 483
 484			for (k = 0; k < m; k++) {
 485				u8 byte = buf[(8 * i + k) * line_length + j / 8];
 486				u8 bit = (byte >> (j % 8)) & 1;
 487
 488				data |= bit << k;
 489			}
 490			data_array[array_idx++] = data;
 491		}
 492
 493		/*
 494		 * In page addressing mode, the start address needs to be reset,
 495		 * and each page then needs to be written out separately.
 496		 */
 497		if (ssd130x->page_address_mode) {
 498			ret = ssd130x_set_page_pos(ssd130x,
 499						   ssd130x->page_offset + i,
 500						   ssd130x->col_offset + x);
 501			if (ret < 0)
 502				goto out_free;
 503
 504			ret = ssd130x_write_data(ssd130x, data_array, width);
 505			if (ret < 0)
 506				goto out_free;
 507
 508			array_idx = 0;
 509		}
 510	}
 511
 512	/* Write out update in one go if we aren't using page addressing mode */
 513	if (!ssd130x->page_address_mode)
 514		ret = ssd130x_write_data(ssd130x, data_array, width * pages);
 515
 516out_free:
 517	kfree(data_array);
 518	return ret;
 519}
 520
 521static void ssd130x_clear_screen(struct ssd130x_device *ssd130x)
 522{
 523	u8 *buf = NULL;
 524	struct drm_rect fullscreen = {
 525		.x1 = 0,
 526		.x2 = ssd130x->width,
 527		.y1 = 0,
 528		.y2 = ssd130x->height,
 529	};
 530
 531	buf = kcalloc(DIV_ROUND_UP(ssd130x->width, 8), ssd130x->height,
 532		      GFP_KERNEL);
 533	if (!buf)
 534		return;
 535
 536	ssd130x_update_rect(ssd130x, buf, &fullscreen);
 537
 538	kfree(buf);
 539}
 540
 541static int ssd130x_fb_blit_rect(struct drm_framebuffer *fb, const struct iosys_map *vmap,
 542				struct drm_rect *rect)
 543{
 544	struct ssd130x_device *ssd130x = drm_to_ssd130x(fb->dev);
 545	struct iosys_map dst;
 546	unsigned int dst_pitch;
 547	int ret = 0;
 548	u8 *buf = NULL;
 549
 550	/* Align y to display page boundaries */
 551	rect->y1 = round_down(rect->y1, 8);
 552	rect->y2 = min_t(unsigned int, round_up(rect->y2, 8), ssd130x->height);
 553
 554	dst_pitch = DIV_ROUND_UP(drm_rect_width(rect), 8);
 555	buf = kcalloc(dst_pitch, drm_rect_height(rect), GFP_KERNEL);
 556	if (!buf)
 557		return -ENOMEM;
 558
 559	ret = drm_gem_fb_begin_cpu_access(fb, DMA_FROM_DEVICE);
 560	if (ret)
 561		goto out_free;
 562
 563	iosys_map_set_vaddr(&dst, buf);
 564	drm_fb_xrgb8888_to_mono(&dst, &dst_pitch, vmap, fb, rect);
 565
 566	drm_gem_fb_end_cpu_access(fb, DMA_FROM_DEVICE);
 567
 568	ssd130x_update_rect(ssd130x, buf, rect);
 569
 570out_free:
 571	kfree(buf);
 572
 573	return ret;
 574}
 575
 576static void ssd130x_primary_plane_helper_atomic_update(struct drm_plane *plane,
 577						       struct drm_atomic_state *state)
 578{
 579	struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(state, plane);
 580	struct drm_plane_state *old_plane_state = drm_atomic_get_old_plane_state(state, plane);
 581	struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
 582	struct drm_atomic_helper_damage_iter iter;
 583	struct drm_device *drm = plane->dev;
 584	struct drm_rect dst_clip;
 585	struct drm_rect damage;
 586	int idx;
 587
 588	if (!drm_dev_enter(drm, &idx))
 589		return;
 590
 591	drm_atomic_helper_damage_iter_init(&iter, old_plane_state, plane_state);
 592	drm_atomic_for_each_plane_damage(&iter, &damage) {
 593		dst_clip = plane_state->dst;
 594
 595		if (!drm_rect_intersect(&dst_clip, &damage))
 596			continue;
 597
 598		ssd130x_fb_blit_rect(plane_state->fb, &shadow_plane_state->data[0], &dst_clip);
 599	}
 600
 601	drm_dev_exit(idx);
 602}
 603
 604static void ssd130x_primary_plane_helper_atomic_disable(struct drm_plane *plane,
 605							struct drm_atomic_state *state)
 606{
 607	struct drm_device *drm = plane->dev;
 608	struct ssd130x_device *ssd130x = drm_to_ssd130x(drm);
 609	int idx;
 610
 611	if (!drm_dev_enter(drm, &idx))
 612		return;
 613
 614	ssd130x_clear_screen(ssd130x);
 615
 616	drm_dev_exit(idx);
 617}
 618
 619static const struct drm_plane_helper_funcs ssd130x_primary_plane_helper_funcs = {
 620	DRM_GEM_SHADOW_PLANE_HELPER_FUNCS,
 621	.atomic_check = drm_plane_helper_atomic_check,
 622	.atomic_update = ssd130x_primary_plane_helper_atomic_update,
 623	.atomic_disable = ssd130x_primary_plane_helper_atomic_disable,
 624};
 625
 626static const struct drm_plane_funcs ssd130x_primary_plane_funcs = {
 627	.update_plane = drm_atomic_helper_update_plane,
 628	.disable_plane = drm_atomic_helper_disable_plane,
 629	.destroy = drm_plane_cleanup,
 630	DRM_GEM_SHADOW_PLANE_FUNCS,
 631};
 632
 633static enum drm_mode_status ssd130x_crtc_helper_mode_valid(struct drm_crtc *crtc,
 634							   const struct drm_display_mode *mode)
 635{
 636	struct ssd130x_device *ssd130x = drm_to_ssd130x(crtc->dev);
 637
 638	if (mode->hdisplay != ssd130x->mode.hdisplay &&
 639	    mode->vdisplay != ssd130x->mode.vdisplay)
 640		return MODE_ONE_SIZE;
 641	else if (mode->hdisplay != ssd130x->mode.hdisplay)
 642		return MODE_ONE_WIDTH;
 643	else if (mode->vdisplay != ssd130x->mode.vdisplay)
 644		return MODE_ONE_HEIGHT;
 645
 646	return MODE_OK;
 647}
 648
 649/*
 650 * The CRTC is always enabled. Screen updates are performed by
 651 * the primary plane's atomic_update function. Disabling clears
 652 * the screen in the primary plane's atomic_disable function.
 653 */
 654static const struct drm_crtc_helper_funcs ssd130x_crtc_helper_funcs = {
 655	.mode_valid = ssd130x_crtc_helper_mode_valid,
 656	.atomic_check = drm_crtc_helper_atomic_check,
 657};
 658
 659static const struct drm_crtc_funcs ssd130x_crtc_funcs = {
 660	.reset = drm_atomic_helper_crtc_reset,
 661	.destroy = drm_crtc_cleanup,
 662	.set_config = drm_atomic_helper_set_config,
 663	.page_flip = drm_atomic_helper_page_flip,
 664	.atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
 665	.atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
 666};
 667
 668static void ssd130x_encoder_helper_atomic_enable(struct drm_encoder *encoder,
 669						 struct drm_atomic_state *state)
 670{
 671	struct drm_device *drm = encoder->dev;
 672	struct ssd130x_device *ssd130x = drm_to_ssd130x(drm);
 673	int ret;
 674
 675	ret = ssd130x_power_on(ssd130x);
 676	if (ret)
 677		return;
 678
 679	ret = ssd130x_init(ssd130x);
 680	if (ret) {
 681		ssd130x_power_off(ssd130x);
 682		return;
 683	}
 684
 685	ssd130x_write_cmd(ssd130x, 1, SSD130X_DISPLAY_ON);
 686
 687	backlight_enable(ssd130x->bl_dev);
 688}
 689
 690static void ssd130x_encoder_helper_atomic_disable(struct drm_encoder *encoder,
 691						  struct drm_atomic_state *state)
 692{
 693	struct drm_device *drm = encoder->dev;
 694	struct ssd130x_device *ssd130x = drm_to_ssd130x(drm);
 695
 696	backlight_disable(ssd130x->bl_dev);
 697
 698	ssd130x_write_cmd(ssd130x, 1, SSD130X_DISPLAY_OFF);
 699
 700	ssd130x_power_off(ssd130x);
 701}
 702
 703static const struct drm_encoder_helper_funcs ssd130x_encoder_helper_funcs = {
 704	.atomic_enable = ssd130x_encoder_helper_atomic_enable,
 705	.atomic_disable = ssd130x_encoder_helper_atomic_disable,
 706};
 707
 708static const struct drm_encoder_funcs ssd130x_encoder_funcs = {
 709	.destroy = drm_encoder_cleanup,
 710};
 711
 712static int ssd130x_connector_helper_get_modes(struct drm_connector *connector)
 713{
 714	struct ssd130x_device *ssd130x = drm_to_ssd130x(connector->dev);
 715	struct drm_display_mode *mode;
 716	struct device *dev = ssd130x->dev;
 717
 718	mode = drm_mode_duplicate(connector->dev, &ssd130x->mode);
 719	if (!mode) {
 720		dev_err(dev, "Failed to duplicated mode\n");
 721		return 0;
 722	}
 723
 724	drm_mode_probed_add(connector, mode);
 725	drm_set_preferred_mode(connector, mode->hdisplay, mode->vdisplay);
 726
 727	/* There is only a single mode */
 728	return 1;
 729}
 730
 731static const struct drm_connector_helper_funcs ssd130x_connector_helper_funcs = {
 732	.get_modes = ssd130x_connector_helper_get_modes,
 733};
 734
 735static const struct drm_connector_funcs ssd130x_connector_funcs = {
 736	.reset = drm_atomic_helper_connector_reset,
 737	.fill_modes = drm_helper_probe_single_connector_modes,
 738	.destroy = drm_connector_cleanup,
 739	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
 740	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
 741};
 742
 743static const struct drm_mode_config_funcs ssd130x_mode_config_funcs = {
 744	.fb_create = drm_gem_fb_create_with_dirty,
 745	.atomic_check = drm_atomic_helper_check,
 746	.atomic_commit = drm_atomic_helper_commit,
 747};
 748
 749static const uint32_t ssd130x_formats[] = {
 750	DRM_FORMAT_XRGB8888,
 751};
 752
 753DEFINE_DRM_GEM_FOPS(ssd130x_fops);
 754
 755static const struct drm_driver ssd130x_drm_driver = {
 756	DRM_GEM_SHMEM_DRIVER_OPS,
 757	.name			= DRIVER_NAME,
 758	.desc			= DRIVER_DESC,
 759	.date			= DRIVER_DATE,
 760	.major			= DRIVER_MAJOR,
 761	.minor			= DRIVER_MINOR,
 762	.driver_features	= DRIVER_ATOMIC | DRIVER_GEM | DRIVER_MODESET,
 763	.fops			= &ssd130x_fops,
 764};
 765
 766static int ssd130x_update_bl(struct backlight_device *bdev)
 767{
 768	struct ssd130x_device *ssd130x = bl_get_data(bdev);
 769	int brightness = backlight_get_brightness(bdev);
 770	int ret;
 771
 772	ssd130x->contrast = brightness;
 773
 774	ret = ssd130x_write_cmd(ssd130x, 1, SSD130X_CONTRAST);
 775	if (ret < 0)
 776		return ret;
 777
 778	ret = ssd130x_write_cmd(ssd130x, 1, ssd130x->contrast);
 779	if (ret < 0)
 780		return ret;
 781
 782	return 0;
 783}
 784
 785static const struct backlight_ops ssd130xfb_bl_ops = {
 786	.update_status	= ssd130x_update_bl,
 787};
 788
 789static void ssd130x_parse_properties(struct ssd130x_device *ssd130x)
 790{
 791	struct device *dev = ssd130x->dev;
 792
 793	if (device_property_read_u32(dev, "solomon,width", &ssd130x->width))
 794		ssd130x->width = 96;
 795
 796	if (device_property_read_u32(dev, "solomon,height", &ssd130x->height))
 797		ssd130x->height = 16;
 798
 799	if (device_property_read_u32(dev, "solomon,page-offset", &ssd130x->page_offset))
 800		ssd130x->page_offset = 1;
 801
 802	if (device_property_read_u32(dev, "solomon,col-offset", &ssd130x->col_offset))
 803		ssd130x->col_offset = 0;
 804
 805	if (device_property_read_u32(dev, "solomon,com-offset", &ssd130x->com_offset))
 806		ssd130x->com_offset = 0;
 807
 808	if (device_property_read_u32(dev, "solomon,prechargep1", &ssd130x->prechargep1))
 809		ssd130x->prechargep1 = 2;
 810
 811	if (device_property_read_u32(dev, "solomon,prechargep2", &ssd130x->prechargep2))
 812		ssd130x->prechargep2 = 2;
 813
 814	if (!device_property_read_u8_array(dev, "solomon,lookup-table",
 815					   ssd130x->lookup_table,
 816					   ARRAY_SIZE(ssd130x->lookup_table)))
 817		ssd130x->lookup_table_set = 1;
 818
 819	ssd130x->seg_remap = !device_property_read_bool(dev, "solomon,segment-no-remap");
 820	ssd130x->com_seq = device_property_read_bool(dev, "solomon,com-seq");
 821	ssd130x->com_lrremap = device_property_read_bool(dev, "solomon,com-lrremap");
 822	ssd130x->com_invdir = device_property_read_bool(dev, "solomon,com-invdir");
 823	ssd130x->area_color_enable =
 824		device_property_read_bool(dev, "solomon,area-color-enable");
 825	ssd130x->low_power = device_property_read_bool(dev, "solomon,low-power");
 826
 827	ssd130x->contrast = 127;
 828	ssd130x->vcomh = ssd130x->device_info->default_vcomh;
 829
 830	/* Setup display timing */
 831	if (device_property_read_u32(dev, "solomon,dclk-div", &ssd130x->dclk_div))
 832		ssd130x->dclk_div = ssd130x->device_info->default_dclk_div;
 833	if (device_property_read_u32(dev, "solomon,dclk-frq", &ssd130x->dclk_frq))
 834		ssd130x->dclk_frq = ssd130x->device_info->default_dclk_frq;
 835}
 836
 837static int ssd130x_init_modeset(struct ssd130x_device *ssd130x)
 838{
 839	struct drm_display_mode *mode = &ssd130x->mode;
 840	struct device *dev = ssd130x->dev;
 841	struct drm_device *drm = &ssd130x->drm;
 842	unsigned long max_width, max_height;
 843	struct drm_plane *primary_plane;
 844	struct drm_crtc *crtc;
 845	struct drm_encoder *encoder;
 846	struct drm_connector *connector;
 847	int ret;
 848
 849	/*
 850	 * Modesetting
 851	 */
 852
 853	ret = drmm_mode_config_init(drm);
 854	if (ret) {
 855		dev_err(dev, "DRM mode config init failed: %d\n", ret);
 856		return ret;
 857	}
 858
 859	mode->type = DRM_MODE_TYPE_DRIVER;
 860	mode->clock = 1;
 861	mode->hdisplay = mode->htotal = ssd130x->width;
 862	mode->hsync_start = mode->hsync_end = ssd130x->width;
 863	mode->vdisplay = mode->vtotal = ssd130x->height;
 864	mode->vsync_start = mode->vsync_end = ssd130x->height;
 865	mode->width_mm = 27;
 866	mode->height_mm = 27;
 867
 868	max_width = max_t(unsigned long, mode->hdisplay, DRM_SHADOW_PLANE_MAX_WIDTH);
 869	max_height = max_t(unsigned long, mode->vdisplay, DRM_SHADOW_PLANE_MAX_HEIGHT);
 870
 871	drm->mode_config.min_width = mode->hdisplay;
 872	drm->mode_config.max_width = max_width;
 873	drm->mode_config.min_height = mode->vdisplay;
 874	drm->mode_config.max_height = max_height;
 875	drm->mode_config.preferred_depth = 32;
 876	drm->mode_config.funcs = &ssd130x_mode_config_funcs;
 877
 878	/* Primary plane */
 879
 880	primary_plane = &ssd130x->primary_plane;
 881	ret = drm_universal_plane_init(drm, primary_plane, 0, &ssd130x_primary_plane_funcs,
 882				       ssd130x_formats, ARRAY_SIZE(ssd130x_formats),
 883				       NULL, DRM_PLANE_TYPE_PRIMARY, NULL);
 884	if (ret) {
 885		dev_err(dev, "DRM primary plane init failed: %d\n", ret);
 886		return ret;
 887	}
 888
 889	drm_plane_helper_add(primary_plane, &ssd130x_primary_plane_helper_funcs);
 890
 891	drm_plane_enable_fb_damage_clips(primary_plane);
 892
 893	/* CRTC */
 894
 895	crtc = &ssd130x->crtc;
 896	ret = drm_crtc_init_with_planes(drm, crtc, primary_plane, NULL,
 897					&ssd130x_crtc_funcs, NULL);
 898	if (ret) {
 899		dev_err(dev, "DRM crtc init failed: %d\n", ret);
 900		return ret;
 901	}
 902
 903	drm_crtc_helper_add(crtc, &ssd130x_crtc_helper_funcs);
 904
 905	/* Encoder */
 906
 907	encoder = &ssd130x->encoder;
 908	ret = drm_encoder_init(drm, encoder, &ssd130x_encoder_funcs,
 909			       DRM_MODE_ENCODER_NONE, NULL);
 910	if (ret) {
 911		dev_err(dev, "DRM encoder init failed: %d\n", ret);
 912		return ret;
 913	}
 914
 915	drm_encoder_helper_add(encoder, &ssd130x_encoder_helper_funcs);
 916
 917	encoder->possible_crtcs = drm_crtc_mask(crtc);
 918
 919	/* Connector */
 920
 921	connector = &ssd130x->connector;
 922	ret = drm_connector_init(drm, connector, &ssd130x_connector_funcs,
 923				 DRM_MODE_CONNECTOR_Unknown);
 924	if (ret) {
 925		dev_err(dev, "DRM connector init failed: %d\n", ret);
 926		return ret;
 927	}
 928
 929	drm_connector_helper_add(connector, &ssd130x_connector_helper_funcs);
 930
 931	ret = drm_connector_attach_encoder(connector, encoder);
 932	if (ret) {
 933		dev_err(dev, "DRM attach connector to encoder failed: %d\n", ret);
 934		return ret;
 935	}
 936
 937	drm_mode_config_reset(drm);
 938
 939	return 0;
 940}
 941
 942static int ssd130x_get_resources(struct ssd130x_device *ssd130x)
 943{
 944	struct device *dev = ssd130x->dev;
 945
 946	ssd130x->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
 947	if (IS_ERR(ssd130x->reset))
 948		return dev_err_probe(dev, PTR_ERR(ssd130x->reset),
 949				     "Failed to get reset gpio\n");
 950
 951	ssd130x->vcc_reg = devm_regulator_get(dev, "vcc");
 952	if (IS_ERR(ssd130x->vcc_reg))
 953		return dev_err_probe(dev, PTR_ERR(ssd130x->vcc_reg),
 954				     "Failed to get VCC regulator\n");
 955
 956	return 0;
 957}
 958
 959struct ssd130x_device *ssd130x_probe(struct device *dev, struct regmap *regmap)
 960{
 961	struct ssd130x_device *ssd130x;
 962	struct backlight_device *bl;
 963	struct drm_device *drm;
 964	int ret;
 965
 966	ssd130x = devm_drm_dev_alloc(dev, &ssd130x_drm_driver,
 967				     struct ssd130x_device, drm);
 968	if (IS_ERR(ssd130x))
 969		return ERR_PTR(dev_err_probe(dev, PTR_ERR(ssd130x),
 970					     "Failed to allocate DRM device\n"));
 971
 972	drm = &ssd130x->drm;
 973
 974	ssd130x->dev = dev;
 975	ssd130x->regmap = regmap;
 976	ssd130x->device_info = device_get_match_data(dev);
 977
 978	if (ssd130x->device_info->page_mode_only)
 979		ssd130x->page_address_mode = 1;
 980
 981	ssd130x_parse_properties(ssd130x);
 982
 983	ret = ssd130x_get_resources(ssd130x);
 984	if (ret)
 985		return ERR_PTR(ret);
 986
 987	bl = devm_backlight_device_register(dev, dev_name(dev), dev, ssd130x,
 988					    &ssd130xfb_bl_ops, NULL);
 989	if (IS_ERR(bl))
 990		return ERR_PTR(dev_err_probe(dev, PTR_ERR(bl),
 991					     "Unable to register backlight device\n"));
 992
 993	bl->props.brightness = ssd130x->contrast;
 994	bl->props.max_brightness = MAX_CONTRAST;
 995	ssd130x->bl_dev = bl;
 996
 997	ret = ssd130x_init_modeset(ssd130x);
 998	if (ret)
 999		return ERR_PTR(ret);
1000
1001	ret = drm_dev_register(drm, 0);
1002	if (ret)
1003		return ERR_PTR(dev_err_probe(dev, ret, "DRM device register failed\n"));
1004
1005	drm_fbdev_generic_setup(drm, 0);
1006
1007	return ssd130x;
1008}
1009EXPORT_SYMBOL_GPL(ssd130x_probe);
1010
1011void ssd130x_remove(struct ssd130x_device *ssd130x)
1012{
1013	drm_dev_unplug(&ssd130x->drm);
1014}
1015EXPORT_SYMBOL_GPL(ssd130x_remove);
1016
1017void ssd130x_shutdown(struct ssd130x_device *ssd130x)
1018{
1019	drm_atomic_helper_shutdown(&ssd130x->drm);
1020}
1021EXPORT_SYMBOL_GPL(ssd130x_shutdown);
1022
1023MODULE_DESCRIPTION(DRIVER_DESC);
1024MODULE_AUTHOR("Javier Martinez Canillas <javierm@redhat.com>");
1025MODULE_LICENSE("GPL v2");