array = ssd1307fb_alloc_array(width * pages, SSD1307FB_DATA); if (!array) return -ENOMEM;
/* * The screen is divided in pages, each having a height of 8 * pixels, and the width of the screen. When sending a byte of * data to the controller, it gives the 8 bits for the current * column. I.e, the first byte are the 8 bits of the first * column, then the 8 bits for the second column, etc. * * * Representation of the screen, assuming it is 5 bits * wide. Each letter-number combination is a bit that controls * one pixel. * * A0 A1 A2 A3 A4 * B0 B1 B2 B3 B4 * C0 C1 C2 C3 C4 * D0 D1 D2 D3 D4 * E0 E1 E2 E3 E4 * F0 F1 F2 F3 F4 * G0 G1 G2 G3 G4 * H0 H1 H2 H3 H4 * * If you want to update this screen, you need to send 5 bytes: * (1) A0 B0 C0 D0 E0 F0 G0 H0 * (2) A1 B1 C1 D1 E1 F1 G1 H1 * (3) A2 B2 C2 D2 E2 F2 G2 H2 * (4) A3 B3 C3 D3 E3 F3 G3 H3 * (5) A4 B4 C4 D4 E4 F4 G4 H4
*/
ret = ssd1307fb_set_col_range(par, par->col_offset + x, width); if (ret < 0) goto out_free;
ret = ssd1307fb_set_page_range(par, par->page_offset + y / 8, pages); if (ret < 0) goto out_free;
for (i = y / 8; i < y / 8 + pages; i++) { int m = 8;
/* Last page may be partial */ if (8 * (i + 1) > par->height)
m = par->height % 8; for (j = x; j < x + width; j++) {
u8 data = 0;
for (k = 0; k < m; k++) {
u8 byte = vmem[(8 * i + k) * line_length +
j / 8];
u8 bit = (byte >> (j % 8)) & 1;
data |= bit << k;
}
array->data[array_idx++] = data;
}
}
ret = ssd1307fb_write_array(par->client, array, width * pages);
if (par->device_info->need_pwm) {
par->pwm = pwm_get(&par->client->dev, NULL); if (IS_ERR(par->pwm)) {
dev_err(&par->client->dev, "Could not get PWM from device tree!\n"); return PTR_ERR(par->pwm);
}
/* Set precharge period in number of ticks from the internal clock */
ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_PRECHARGE_PERIOD); if (ret < 0) return ret;
/* Set VCOMH */
ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_VCOMH); if (ret < 0) return ret;
ret = ssd1307fb_write_cmd(par->client, par->vcomh); if (ret < 0) return ret;
/* Turn on the DC-DC Charge Pump */
ret = ssd1307fb_write_cmd(par->client, SSD1307FB_CHARGE_PUMP); if (ret < 0) return ret;
ret = ssd1307fb_write_cmd(par->client,
BIT(4) | (par->device_info->need_chargepump ? BIT(2) : 0)); if (ret < 0) return ret;
/* Set lookup table */ if (par->lookup_table_set) { int i;
ret = ssd1307fb_write_cmd(par->client,
SSD1307FB_SET_LOOKUP_TABLE); if (ret < 0) return ret;
for (i = 0; i < ARRAY_SIZE(par->lookup_table); ++i) {
u8 val = par->lookup_table[i];
if (val < 31 || val > 63)
dev_warn(&par->client->dev, "lookup table index %d value out of range 31 <= %d <= 63\n",
i, val);
ret = ssd1307fb_write_cmd(par->client, val); if (ret < 0) return ret;
}
}
/* Switch to horizontal addressing mode */
ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_ADDRESS_MODE); if (ret < 0) return ret;
ret = ssd1307fb_write_cmd(par->client,
SSD1307FB_SET_ADDRESS_MODE_HORIZONTAL); if (ret < 0) return ret;
/* Clear the screen */
ret = ssd1307fb_update_display(par); if (ret < 0) return ret;
/* Turn on the display */
ret = ssd1307fb_write_cmd(par->client, SSD1307FB_DISPLAY_ON); if (ret < 0) return ret;
return 0;
}
staticint ssd1307fb_update_bl(struct backlight_device *bdev)
{ struct ssd1307fb_par *par = bl_get_data(bdev); int ret; int brightness = bdev->props.brightness;
par->contrast = brightness;
ret = ssd1307fb_write_cmd(par->client, SSD1307FB_CONTRAST); if (ret < 0) return ret;
ret = ssd1307fb_write_cmd(par->client, par->contrast); if (ret < 0) return ret; return 0;
}
info = framebuffer_alloc(sizeof(struct ssd1307fb_par), dev); if (!info) return -ENOMEM;
par = info->par;
par->info = info;
par->client = client;
par->device_info = device_get_match_data(dev);
par->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW); if (IS_ERR(par->reset)) {
ret = dev_err_probe(dev, PTR_ERR(par->reset), "failed to get reset gpio\n"); goto fb_alloc_error;
}
par->vbat_reg = devm_regulator_get_optional(dev, "vbat"); if (IS_ERR(par->vbat_reg)) {
ret = PTR_ERR(par->vbat_reg); if (ret == -ENODEV) {
par->vbat_reg = NULL;
} else {
dev_err_probe(dev, ret, "failed to get VBAT regulator\n"); goto fb_alloc_error;
}
}
if (device_property_read_u32(dev, "solomon,width", &par->width))
par->width = 96;
if (device_property_read_u32(dev, "solomon,height", &par->height))
par->height = 16;
if (device_property_read_u32(dev, "solomon,page-offset", &par->page_offset))
par->page_offset = 1;
if (device_property_read_u32(dev, "solomon,col-offset", &par->col_offset))
par->col_offset = 0;
if (device_property_read_u32(dev, "solomon,com-offset", &par->com_offset))
par->com_offset = 0;
if (device_property_read_u32(dev, "solomon,prechargep1", &par->prechargep1))
par->prechargep1 = 2;
if (device_property_read_u32(dev, "solomon,prechargep2", &par->prechargep2))
par->prechargep2 = 2;
if (!device_property_read_u8_array(dev, "solomon,lookup-table",
par->lookup_table,
ARRAY_SIZE(par->lookup_table)))
par->lookup_table_set = 1;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.