Linux Framebuffer Layer development
 help / color / mirror / Atom feed
* Re: [PATCH 2/5] backlight: Add Sanyo LV5207LP backlight driver
From: Jingoo Han @ 2012-11-26  9:48 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: akpm, linux-kernel, linux-sh@vger.kernel.org,
	linux-fbdev@vger.kernel.org, Paul Mundt, Magnus Damm,
	Richard Purdie, Kuninori Morimoto, Jingoo Han
In-Reply-To: <1353688515-30458-3-git-send-email-laurent.pinchart+renesas@ideasonboard.com>

T24gU2F0dXJkYXksIE5vdmVtYmVyIDI0LCAyMDEyIDE6MzUgQU0sIExhdXJlbnQgUGluY2hhcnQg
d3JvdGUNCj4gDQo+IFNpZ25lZC1vZmYtYnk6IExhdXJlbnQgUGluY2hhcnQgPGxhdXJlbnQucGlu
Y2hhcnRAaWRlYXNvbmJvYXJkLmNvbT4NCg0KQ0MnZWQgQW5kcmV3IE1vcnRvbg0KDQpBY2tlZC1i
eTogSmluZ29vIEhhbiA8amcxLmhhbkBzYW1zdW5nLmNvbT4NCg0KQmVzdCByZWdhcmRzLA0KSmlu
Z29vIEhhbg0KDQo+IC0tLQ0KPiAgZHJpdmVycy92aWRlby9iYWNrbGlnaHQvS2NvbmZpZyAgICAg
ICAgfCAgICA2ICsNCj4gIGRyaXZlcnMvdmlkZW8vYmFja2xpZ2h0L01ha2VmaWxlICAgICAgIHwg
ICAgMSArDQo+ICBkcml2ZXJzL3ZpZGVvL2JhY2tsaWdodC9sdjUyMDdscC5jICAgICB8ICAxNzEg
KysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysNCj4gIGluY2x1ZGUvbGludXgvcGxhdGZv
cm1fZGF0YS9sdjUyMDdscC5oIHwgICAyMCArKysrDQo+ICA0IGZpbGVzIGNoYW5nZWQsIDE5OCBp
bnNlcnRpb25zKCspLCAwIGRlbGV0aW9ucygtKQ0KPiAgY3JlYXRlIG1vZGUgMTAwNjQ0IGRyaXZl
cnMvdmlkZW8vYmFja2xpZ2h0L2x2NTIwN2xwLmMNCj4gIGNyZWF0ZSBtb2RlIDEwMDY0NCBpbmNs
dWRlL2xpbnV4L3BsYXRmb3JtX2RhdGEvbHY1MjA3bHAuaA0KPiANCj4gZGlmZiAtLWdpdCBhL2Ry
aXZlcnMvdmlkZW8vYmFja2xpZ2h0L0tjb25maWcgYi9kcml2ZXJzL3ZpZGVvL2JhY2tsaWdodC9L
Y29uZmlnDQo+IGluZGV4IDI1OTQ0MmQuLjkyY2U1YWEgMTAwNjQ0DQo+IC0tLSBhL2RyaXZlcnMv
dmlkZW8vYmFja2xpZ2h0L0tjb25maWcNCj4gKysrIGIvZHJpdmVycy92aWRlby9iYWNrbGlnaHQv
S2NvbmZpZw0KPiBAQCAtMzk3LDYgKzM5NywxMiBAQCBjb25maWcgQkFDS0xJR0hUX0dQSU8NCj4g
IAkgIElmIHlvdSBoYXZlIGEgTENEIGJhY2tsaWdodCBhZGp1c3RhYmxlIGJ5IEdQSU8sIHNheSBZ
IHRvIGVuYWJsZQ0KPiAgCSAgdGhpcyBkcml2ZXIuDQo+IA0KPiArY29uZmlnIEJBQ0tMSUdIVF9M
VjUyMDdMUA0KPiArCXRyaXN0YXRlICJTYW55byBMVjUyMDdMUCBCYWNrbGlnaHQiDQo+ICsJZGVw
ZW5kcyBvbiBJMkMNCj4gKwloZWxwDQo+ICsJICBJZiB5b3UgaGF2ZSBhIFNhbnlvIExWNTIwN0xQ
IHNheSBZIHRvIGVuYWJsZSB0aGUgYmFja2xpZ2h0IGRyaXZlci4NCj4gKw0KPiAgZW5kaWYgIyBC
QUNLTElHSFRfQ0xBU1NfREVWSUNFDQo+IA0KPiAgZW5kaWYgIyBCQUNLTElHSFRfTENEX1NVUFBP
UlQNCj4gZGlmZiAtLWdpdCBhL2RyaXZlcnMvdmlkZW8vYmFja2xpZ2h0L01ha2VmaWxlIGIvZHJp
dmVycy92aWRlby9iYWNrbGlnaHQvTWFrZWZpbGUNCj4gaW5kZXggZWM5MWM0YS4uMTI1YjhhZCAx
MDA2NDQNCj4gLS0tIGEvZHJpdmVycy92aWRlby9iYWNrbGlnaHQvTWFrZWZpbGUNCj4gKysrIGIv
ZHJpdmVycy92aWRlby9iYWNrbGlnaHQvTWFrZWZpbGUNCj4gQEAgLTQ2LDMgKzQ2LDQgQEAgb2Jq
LSQoQ09ORklHX0JBQ0tMSUdIVF9BQVQyODcwKSArPSBhYXQyODcwX2JsLm8NCj4gIG9iai0kKENP
TkZJR19CQUNLTElHSFRfT1QyMDApICs9IG90MjAwX2JsLm8NCj4gIG9iai0kKENPTkZJR19CQUNL
TElHSFRfVFBTNjUyMTcpICs9IHRwczY1MjE3X2JsLm8NCj4gIG9iai0kKENPTkZJR19CQUNLTElH
SFRfR1BJTykJKz0gZ3Bpb19iYWNrbGlnaHQubw0KPiArb2JqLSQoQ09ORklHX0JBQ0tMSUdIVF9M
VjUyMDdMUCkJKz0gbHY1MjA3bHAubw0KPiBkaWZmIC0tZ2l0IGEvZHJpdmVycy92aWRlby9iYWNr
bGlnaHQvbHY1MjA3bHAuYyBiL2RyaXZlcnMvdmlkZW8vYmFja2xpZ2h0L2x2NTIwN2xwLmMNCj4g
bmV3IGZpbGUgbW9kZSAxMDA2NDQNCj4gaW5kZXggMDAwMDAwMC4uYjA2ZjM1Yw0KPiAtLS0gL2Rl
di9udWxsDQo+ICsrKyBiL2RyaXZlcnMvdmlkZW8vYmFja2xpZ2h0L2x2NTIwN2xwLmMNCj4gQEAg
LTAsMCArMSwxNzEgQEANCj4gKy8qDQo+ICsgKiBTYW55byBMVjUyMDdMUCBMRUQgRHJpdmVyDQo+
ICsgKg0KPiArICogQ29weXJpZ2h0IChDKSAyMDEyIElkZWFzIG9uIGJvYXJkIFNQUkwNCj4gKyAq
DQo+ICsgKiBDb250YWN0OiBMYXVyZW50IFBpbmNoYXJ0IDxsYXVyZW50LnBpbmNoYXJ0QGlkZWFz
b25ib2FyZC5jb20+DQo+ICsgKg0KPiArICogVGhpcyBwcm9ncmFtIGlzIGZyZWUgc29mdHdhcmU7
IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vciBtb2RpZnkNCj4gKyAqIGl0IHVuZGVyIHRo
ZSB0ZXJtcyBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgdmVyc2lvbiAyIGFzDQo+
ICsgKiBwdWJsaXNoZWQgYnkgdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbi4NCj4gKyAqLw0K
PiArDQo+ICsjaW5jbHVkZSA8bGludXgvYmFja2xpZ2h0Lmg+DQo+ICsjaW5jbHVkZSA8bGludXgv
ZXJyLmg+DQo+ICsjaW5jbHVkZSA8bGludXgvZmIuaD4NCj4gKyNpbmNsdWRlIDxsaW51eC9pMmMu
aD4NCj4gKyNpbmNsdWRlIDxsaW51eC9tb2R1bGUuaD4NCj4gKyNpbmNsdWRlIDxsaW51eC9zbGFi
Lmg+DQo+ICsjaW5jbHVkZSA8bGludXgvcGxhdGZvcm1fZGF0YS9sdjUyMDdscC5oPg0KPiArDQo+
ICsjZGVmaW5lIExWNTIwN0xQX0NUUkwxCQkJMHgwMA0KPiArI2RlZmluZSBMVjUyMDdMUF9DUFNX
CQkJKDEgPDwgNykNCj4gKyNkZWZpbmUgTFY1MjA3TFBfU0NURU4JCQkoMSA8PCA2KQ0KPiArI2Rl
ZmluZSBMVjUyMDdMUF9DMTAJCQkoMSA8PCA1KQ0KPiArI2RlZmluZSBMVjUyMDdMUF9DS1NXCQkJ
KDEgPDwgNCkNCj4gKyNkZWZpbmUgTFY1MjA3TFBfUlNXCQkJKDEgPDwgMykNCj4gKyNkZWZpbmUg
TFY1MjA3TFBfR1NXCQkJKDEgPDwgMikNCj4gKyNkZWZpbmUgTFY1MjA3TFBfQlNXCQkJKDEgPDwg
MSkNCj4gKyNkZWZpbmUgTFY1MjA3TFBfQ1RSTDIJCQkweDAxDQo+ICsjZGVmaW5lIExWNTIwN0xQ
X01TVwkJCSgxIDw8IDcpDQo+ICsjZGVmaW5lIExWNTIwN0xQX01MRUQ0CQkJKDEgPDwgNikNCj4g
KyNkZWZpbmUgTFY1MjA3TFBfUkVECQkJMHgwMg0KPiArI2RlZmluZSBMVjUyMDdMUF9HUkVFTgkJ
CTB4MDMNCj4gKyNkZWZpbmUgTFY1MjA3TFBfQkxVRQkJCTB4MDQNCj4gKw0KPiArI2RlZmluZSBM
VjUyMDdMUF9NQVhfQlJJR0hUTkVTUwkJMzINCj4gKw0KPiArc3RydWN0IGx2NTIwN2xwIHsNCj4g
KwlzdHJ1Y3QgaTJjX2NsaWVudCAqY2xpZW50Ow0KPiArCXN0cnVjdCBiYWNrbGlnaHRfZGV2aWNl
ICpiYWNrbGlnaHQ7DQo+ICsJc3RydWN0IGx2NTIwN2xwX3BsYXRmb3JtX2RhdGEgKnBkYXRhOw0K
PiArfTsNCj4gKw0KPiArc3RhdGljIGludCBsdjUyMDdscF93cml0ZShzdHJ1Y3QgbHY1MjA3bHAg
Kmx2LCB1OCByZWcsIHU4IGRhdGEpDQo+ICt7DQo+ICsJcmV0dXJuIGkyY19zbWJ1c193cml0ZV9i
eXRlX2RhdGEobHYtPmNsaWVudCwgcmVnLCBkYXRhKTsNCj4gK30NCj4gKw0KPiArc3RhdGljIGlu
dCBsdjUyMDdscF9iYWNrbGlnaHRfdXBkYXRlX3N0YXR1cyhzdHJ1Y3QgYmFja2xpZ2h0X2Rldmlj
ZSAqYmFja2xpZ2h0KQ0KPiArew0KPiArCXN0cnVjdCBsdjUyMDdscCAqbHYgPSBibF9nZXRfZGF0
YShiYWNrbGlnaHQpOw0KPiArCWludCBicmlnaHRuZXNzID0gYmFja2xpZ2h0LT5wcm9wcy5icmln
aHRuZXNzOw0KPiArDQo+ICsJaWYgKGJhY2tsaWdodC0+cHJvcHMucG93ZXIgIT0gRkJfQkxBTktf
VU5CTEFOSyB8fA0KPiArCSAgICBiYWNrbGlnaHQtPnByb3BzLmZiX2JsYW5rICE9IEZCX0JMQU5L
X1VOQkxBTksgfHwNCj4gKwkgICAgYmFja2xpZ2h0LT5wcm9wcy5zdGF0ZSAmIChCTF9DT1JFX1NV
U1BFTkRFRCB8IEJMX0NPUkVfRkJCTEFOSykpDQo+ICsJCWJyaWdodG5lc3MgPSAwOw0KPiArDQo+
ICsJaWYgKGJyaWdodG5lc3MpIHsNCj4gKwkJbHY1MjA3bHBfd3JpdGUobHYsIExWNTIwN0xQX0NU
UkwxLA0KPiArCQkJICAgICAgIExWNTIwN0xQX0NQU1cgfCBMVjUyMDdMUF9DMTAgfCBMVjUyMDdM
UF9DS1NXKTsNCj4gKwkJbHY1MjA3bHBfd3JpdGUobHYsIExWNTIwN0xQX0NUUkwyLA0KPiArCQkJ
ICAgICAgIExWNTIwN0xQX01TVyB8IExWNTIwN0xQX01MRUQ0IHwNCj4gKwkJCSAgICAgICAoYnJp
Z2h0bmVzcyAtIDEpKTsNCj4gKwl9IGVsc2Ugew0KPiArCQlsdjUyMDdscF93cml0ZShsdiwgTFY1
MjA3TFBfQ1RSTDEsIDApOw0KPiArCQlsdjUyMDdscF93cml0ZShsdiwgTFY1MjA3TFBfQ1RSTDIs
IDApOw0KPiArCX0NCj4gKw0KPiArCXJldHVybiAwOw0KPiArfQ0KPiArDQo+ICtzdGF0aWMgaW50
IGx2NTIwN2xwX2JhY2tsaWdodF9nZXRfYnJpZ2h0bmVzcyhzdHJ1Y3QgYmFja2xpZ2h0X2Rldmlj
ZSAqYmFja2xpZ2h0KQ0KPiArew0KPiArCXJldHVybiBiYWNrbGlnaHQtPnByb3BzLmJyaWdodG5l
c3M7DQo+ICt9DQo+ICsNCj4gK3N0YXRpYyBpbnQgbHY1MjA3bHBfYmFja2xpZ2h0X2NoZWNrX2Zi
KHN0cnVjdCBiYWNrbGlnaHRfZGV2aWNlICpiYWNrbGlnaHQsDQo+ICsJCQkJICAgICAgIHN0cnVj
dCBmYl9pbmZvICppbmZvKQ0KPiArew0KPiArCXN0cnVjdCBsdjUyMDdscCAqbHYgPSBibF9nZXRf
ZGF0YShiYWNrbGlnaHQpOw0KPiArDQo+ICsJcmV0dXJuIGx2LT5wZGF0YS0+ZmJkZXYgPT0gaW5m
by0+ZGV2Ow0KPiArfQ0KPiArDQo+ICtzdGF0aWMgY29uc3Qgc3RydWN0IGJhY2tsaWdodF9vcHMg
bHY1MjA3bHBfYmFja2xpZ2h0X29wcyA9IHsNCj4gKwkub3B0aW9ucwk9IEJMX0NPUkVfU1VTUEVO
RFJFU1VNRSwNCj4gKwkudXBkYXRlX3N0YXR1cwk9IGx2NTIwN2xwX2JhY2tsaWdodF91cGRhdGVf
c3RhdHVzLA0KPiArCS5nZXRfYnJpZ2h0bmVzcwk9IGx2NTIwN2xwX2JhY2tsaWdodF9nZXRfYnJp
Z2h0bmVzcywNCj4gKwkuY2hlY2tfZmIJPSBsdjUyMDdscF9iYWNrbGlnaHRfY2hlY2tfZmIsDQo+
ICt9Ow0KPiArDQo+ICtzdGF0aWMgaW50IGx2NTIwN2xwX3Byb2JlKHN0cnVjdCBpMmNfY2xpZW50
ICpjbGllbnQsDQo+ICsJCQkgIGNvbnN0IHN0cnVjdCBpMmNfZGV2aWNlX2lkICppZCkNCj4gK3sN
Cj4gKwlzdHJ1Y3QgbHY1MjA3bHBfcGxhdGZvcm1fZGF0YSAqcGRhdGEgPSBjbGllbnQtPmRldi5w
bGF0Zm9ybV9kYXRhOw0KPiArCXN0cnVjdCBiYWNrbGlnaHRfZGV2aWNlICpiYWNrbGlnaHQ7DQo+
ICsJc3RydWN0IGJhY2tsaWdodF9wcm9wZXJ0aWVzIHByb3BzOw0KPiArCXN0cnVjdCBsdjUyMDds
cCAqbHY7DQo+ICsNCj4gKwlpZiAocGRhdGEgPT0gTlVMTCkgew0KPiArCQlkZXZfZXJyKCZjbGll
bnQtPmRldiwgIk5vIHBsYXRmb3JtIGRhdGEgc3VwcGxpZWRcbiIpOw0KPiArCQlyZXR1cm4gLUVJ
TlZBTDsNCj4gKwl9DQo+ICsNCj4gKwlpZiAoIWkyY19jaGVja19mdW5jdGlvbmFsaXR5KGNsaWVu
dC0+YWRhcHRlciwNCj4gKwkJCQkgICAgIEkyQ19GVU5DX1NNQlVTX0JZVEVfREFUQSkpIHsNCj4g
KwkJZGV2X3dhcm4oJmNsaWVudC0+ZGV2LA0KPiArCQkJICJJMkMgYWRhcHRlciBkb2Vzbid0IHN1
cHBvcnQgSTJDX0ZVTkNfU01CVVNfQllURVxuIik7DQo+ICsJCXJldHVybiAtRUlPOw0KPiArCX0N
Cj4gKw0KPiArCWx2ID0gZGV2bV9remFsbG9jKCZjbGllbnQtPmRldiwgc2l6ZW9mKCpsdiksIEdG
UF9LRVJORUwpOw0KPiArCWlmICghbHYpDQo+ICsJCXJldHVybiAtRU5PTUVNOw0KPiArDQo+ICsJ
bHYtPmNsaWVudCA9IGNsaWVudDsNCj4gKwlsdi0+cGRhdGEgPSBwZGF0YTsNCj4gKw0KPiArCW1l
bXNldCgmcHJvcHMsIDAsIHNpemVvZihwcm9wcykpOw0KPiArCXByb3BzLnR5cGUgPSBCQUNLTElH
SFRfUkFXOw0KPiArCXByb3BzLm1heF9icmlnaHRuZXNzID0gbWluX3QodW5zaWduZWQgaW50LCBw
ZGF0YS0+bWF4X3ZhbHVlLA0KPiArCQkJCSAgICAgTFY1MjA3TFBfTUFYX0JSSUdIVE5FU1MpOw0K
PiArCXByb3BzLmJyaWdodG5lc3MgPSBjbGFtcF90KHVuc2lnbmVkIGludCwgcGRhdGEtPmRlZl92
YWx1ZSwgMCwNCj4gKwkJCQkgICBwcm9wcy5tYXhfYnJpZ2h0bmVzcyk7DQo+ICsNCj4gKwliYWNr
bGlnaHQgPSBiYWNrbGlnaHRfZGV2aWNlX3JlZ2lzdGVyKGRldl9uYW1lKCZjbGllbnQtPmRldiks
DQo+ICsJCQkJCSAgICAgICZsdi0+Y2xpZW50LT5kZXYsIGx2LA0KPiArCQkJCQkgICAgICAmbHY1
MjA3bHBfYmFja2xpZ2h0X29wcywgJnByb3BzKTsNCj4gKwlpZiAoSVNfRVJSKGJhY2tsaWdodCkp
IHsNCj4gKwkJZGV2X2VycigmY2xpZW50LT5kZXYsICJmYWlsZWQgdG8gcmVnaXN0ZXIgYmFja2xp
Z2h0XG4iKTsNCj4gKwkJcmV0dXJuIFBUUl9FUlIoYmFja2xpZ2h0KTsNCj4gKwl9DQo+ICsNCj4g
KwliYWNrbGlnaHRfdXBkYXRlX3N0YXR1cyhiYWNrbGlnaHQpOw0KPiArCWkyY19zZXRfY2xpZW50
ZGF0YShjbGllbnQsIGJhY2tsaWdodCk7DQo+ICsNCj4gKwlyZXR1cm4gMDsNCj4gK30NCj4gKw0K
PiArc3RhdGljIGludCBsdjUyMDdscF9yZW1vdmUoc3RydWN0IGkyY19jbGllbnQgKmNsaWVudCkN
Cj4gK3sNCj4gKwlzdHJ1Y3QgYmFja2xpZ2h0X2RldmljZSAqYmFja2xpZ2h0ID0gaTJjX2dldF9j
bGllbnRkYXRhKGNsaWVudCk7DQo+ICsNCj4gKwliYWNrbGlnaHQtPnByb3BzLmJyaWdodG5lc3Mg
PSAwOw0KPiArCWJhY2tsaWdodF91cGRhdGVfc3RhdHVzKGJhY2tsaWdodCk7DQo+ICsJYmFja2xp
Z2h0X2RldmljZV91bnJlZ2lzdGVyKGJhY2tsaWdodCk7DQo+ICsNCj4gKwlyZXR1cm4gMDsNCj4g
K30NCj4gKw0KPiArc3RhdGljIGNvbnN0IHN0cnVjdCBpMmNfZGV2aWNlX2lkIGx2NTIwN2xwX2lk
c1tdID0gew0KPiArCXsgImx2NTIwN2xwIiwgMCB9LA0KPiArCXsgfQ0KPiArfTsNCj4gK01PRFVM
RV9ERVZJQ0VfVEFCTEUoaTJjLCBsdjUyMDdscF9pZHMpOw0KPiArDQo+ICtzdGF0aWMgc3RydWN0
IGkyY19kcml2ZXIgbHY1MjA3bHBfZHJpdmVyID0gew0KPiArCS5kcml2ZXIgPSB7DQo+ICsJCS5u
YW1lID0gImx2NTIwN2xwIiwNCj4gKwl9LA0KPiArCS5wcm9iZSA9IGx2NTIwN2xwX3Byb2JlLA0K
PiArCS5yZW1vdmUgPSBsdjUyMDdscF9yZW1vdmUsDQo+ICsJLmlkX3RhYmxlID0gbHY1MjA3bHBf
aWRzLA0KPiArfTsNCj4gKw0KPiArbW9kdWxlX2kyY19kcml2ZXIobHY1MjA3bHBfZHJpdmVyKTsN
Cj4gKw0KPiArTU9EVUxFX0RFU0NSSVBUSU9OKCJTYW55byBMVjUyMDdMUCBCYWNrbGlnaHQgRHJp
dmVyIik7DQo+ICtNT0RVTEVfQVVUSE9SKCJMYXVyZW50IFBpbmNoYXJ0IDxsYXVyZW50LnBpbmNo
YXJ0QGlkZWFzb25ib2FyZC5jb20+Iik7DQo+ICtNT0RVTEVfTElDRU5TRSgiR1BMIik7DQo+IGRp
ZmYgLS1naXQgYS9pbmNsdWRlL2xpbnV4L3BsYXRmb3JtX2RhdGEvbHY1MjA3bHAuaCBiL2luY2x1
ZGUvbGludXgvcGxhdGZvcm1fZGF0YS9sdjUyMDdscC5oDQo+IG5ldyBmaWxlIG1vZGUgMTAwNjQ0
DQo+IGluZGV4IDAwMDAwMDAuLmFjOTVjYjENCj4gLS0tIC9kZXYvbnVsbA0KPiArKysgYi9pbmNs
dWRlL2xpbnV4L3BsYXRmb3JtX2RhdGEvbHY1MjA3bHAuaA0KPiBAQCAtMCwwICsxLDIwIEBADQo+
ICsvKg0KPiArICogbHY1MjA3bHAuaCAtIFNhbnlvIExWNTIwN0xQIExFRHMgRHJpdmVyDQo+ICsg
Kg0KPiArICogVGhpcyBwcm9ncmFtIGlzIGZyZWUgc29mdHdhcmU7IHlvdSBjYW4gcmVkaXN0cmli
dXRlIGl0IGFuZC9vciBtb2RpZnkNCj4gKyAqIGl0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05V
IEdlbmVyYWwgUHVibGljIExpY2Vuc2UgdmVyc2lvbiAyIGFzDQo+ICsgKiBwdWJsaXNoZWQgYnkg
dGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbi4NCj4gKyAqLw0KPiArI2lmbmRlZiBfX0xWNTIw
N0xQX0hfXw0KPiArI2RlZmluZSBfX0xWNTIwN0xQX0hfXw0KPiArDQo+ICtzdHJ1Y3QgZGV2aWNl
Ow0KPiArDQo+ICtzdHJ1Y3QgbHY1MjA3bHBfcGxhdGZvcm1fZGF0YSB7DQo+ICsJc3RydWN0IGRl
dmljZSAqZmJkZXY7DQo+ICsJdW5zaWduZWQgaW50IG1heF92YWx1ZTsNCj4gKwl1bnNpZ25lZCBp
bnQgZGVmX3ZhbHVlOw0KPiArfTsNCj4gKw0KPiArI2VuZGlmDQo+ICsNCj4gLS0NCj4gMS43Ljgu
Ng0KPiANCj4gLS0NCj4gVG8gdW5zdWJzY3JpYmUgZnJvbSB0aGlzIGxpc3Q6IHNlbmQgdGhlIGxp
bmUgInVuc3Vic2NyaWJlIGxpbnV4LWZiZGV2IiBpbg0KPiB0aGUgYm9keSBvZiBhIG1lc3NhZ2Ug
dG8gbWFqb3Jkb21vQHZnZXIua2VybmVsLm9yZw0KPiBNb3JlIG1ham9yZG9tbyBpbmZvIGF0ICBo
dHRwOi8vdmdlci5rZXJuZWwub3JnL21ham9yZG9tby1pbmZvLmh0bWwNCg=



^ permalink raw reply

* Re: [PATCH 2/5] backlight: Add Sanyo LV5207LP backlight driver
From: Jingoo Han @ 2012-11-26  9:38 UTC (permalink / raw)
  To: 'Laurent Pinchart'
  Cc: 'Andrew Morton', 'LKML', linux-sh, linux-fbdev,
	'Paul Mundt', 'Magnus Damm',
	'Richard Purdie', 'Kuninori Morimoto',
	'Jingoo Han'
In-Reply-To: <1353688515-30458-3-git-send-email-laurent.pinchart+renesas@ideasonboard.com>

On Saturday, November 24, 2012 1:35 AM, Laurent Pinchart wrote
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>


CC'ed Andrew Morton


Acked-by: Jingoo Han <jg1.han@samsung.com>


Best regards,
Jingoo Han

> ---
>  drivers/video/backlight/Kconfig        |    6 +
>  drivers/video/backlight/Makefile       |    1 +
>  drivers/video/backlight/lv5207lp.c     |  171 ++++++++++++++++++++++++++++++++
>  include/linux/platform_data/lv5207lp.h |   20 ++++
>  4 files changed, 198 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/video/backlight/lv5207lp.c
>  create mode 100644 include/linux/platform_data/lv5207lp.h
> 
> diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig
> index 259442d..92ce5aa 100644
> --- a/drivers/video/backlight/Kconfig
> +++ b/drivers/video/backlight/Kconfig
> @@ -397,6 +397,12 @@ config BACKLIGHT_GPIO
>  	  If you have a LCD backlight adjustable by GPIO, say Y to enable
>  	  this driver.
> 
> +config BACKLIGHT_LV5207LP
> +	tristate "Sanyo LV5207LP Backlight"
> +	depends on I2C
> +	help
> +	  If you have a Sanyo LV5207LP say Y to enable the backlight driver.
> +
>  endif # BACKLIGHT_CLASS_DEVICE
> 
>  endif # BACKLIGHT_LCD_SUPPORT
> diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile
> index ec91c4a..125b8ad 100644
> --- a/drivers/video/backlight/Makefile
> +++ b/drivers/video/backlight/Makefile
> @@ -46,3 +46,4 @@ obj-$(CONFIG_BACKLIGHT_AAT2870) += aat2870_bl.o
>  obj-$(CONFIG_BACKLIGHT_OT200) += ot200_bl.o
>  obj-$(CONFIG_BACKLIGHT_TPS65217) += tps65217_bl.o
>  obj-$(CONFIG_BACKLIGHT_GPIO)	+= gpio_backlight.o
> +obj-$(CONFIG_BACKLIGHT_LV5207LP)	+= lv5207lp.o
> diff --git a/drivers/video/backlight/lv5207lp.c b/drivers/video/backlight/lv5207lp.c
> new file mode 100644
> index 0000000..b06f35c
> --- /dev/null
> +++ b/drivers/video/backlight/lv5207lp.c
> @@ -0,0 +1,171 @@
> +/*
> + * Sanyo LV5207LP LED Driver
> + *
> + * Copyright (C) 2012 Ideas on board SPRL
> + *
> + * Contact: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#include <linux/backlight.h>
> +#include <linux/err.h>
> +#include <linux/fb.h>
> +#include <linux/i2c.h>
> +#include <linux/module.h>
> +#include <linux/slab.h>
> +#include <linux/platform_data/lv5207lp.h>
> +
> +#define LV5207LP_CTRL1			0x00
> +#define LV5207LP_CPSW			(1 << 7)
> +#define LV5207LP_SCTEN			(1 << 6)
> +#define LV5207LP_C10			(1 << 5)
> +#define LV5207LP_CKSW			(1 << 4)
> +#define LV5207LP_RSW			(1 << 3)
> +#define LV5207LP_GSW			(1 << 2)
> +#define LV5207LP_BSW			(1 << 1)
> +#define LV5207LP_CTRL2			0x01
> +#define LV5207LP_MSW			(1 << 7)
> +#define LV5207LP_MLED4			(1 << 6)
> +#define LV5207LP_RED			0x02
> +#define LV5207LP_GREEN			0x03
> +#define LV5207LP_BLUE			0x04
> +
> +#define LV5207LP_MAX_BRIGHTNESS		32
> +
> +struct lv5207lp {
> +	struct i2c_client *client;
> +	struct backlight_device *backlight;
> +	struct lv5207lp_platform_data *pdata;
> +};
> +
> +static int lv5207lp_write(struct lv5207lp *lv, u8 reg, u8 data)
> +{
> +	return i2c_smbus_write_byte_data(lv->client, reg, data);
> +}
> +
> +static int lv5207lp_backlight_update_status(struct backlight_device *backlight)
> +{
> +	struct lv5207lp *lv = bl_get_data(backlight);
> +	int brightness = backlight->props.brightness;
> +
> +	if (backlight->props.power != FB_BLANK_UNBLANK ||
> +	    backlight->props.fb_blank != FB_BLANK_UNBLANK ||
> +	    backlight->props.state & (BL_CORE_SUSPENDED | BL_CORE_FBBLANK))
> +		brightness = 0;
> +
> +	if (brightness) {
> +		lv5207lp_write(lv, LV5207LP_CTRL1,
> +			       LV5207LP_CPSW | LV5207LP_C10 | LV5207LP_CKSW);
> +		lv5207lp_write(lv, LV5207LP_CTRL2,
> +			       LV5207LP_MSW | LV5207LP_MLED4 |
> +			       (brightness - 1));
> +	} else {
> +		lv5207lp_write(lv, LV5207LP_CTRL1, 0);
> +		lv5207lp_write(lv, LV5207LP_CTRL2, 0);
> +	}
> +
> +	return 0;
> +}
> +
> +static int lv5207lp_backlight_get_brightness(struct backlight_device *backlight)
> +{
> +	return backlight->props.brightness;
> +}
> +
> +static int lv5207lp_backlight_check_fb(struct backlight_device *backlight,
> +				       struct fb_info *info)
> +{
> +	struct lv5207lp *lv = bl_get_data(backlight);
> +
> +	return lv->pdata->fbdev = info->dev;
> +}
> +
> +static const struct backlight_ops lv5207lp_backlight_ops = {
> +	.options	= BL_CORE_SUSPENDRESUME,
> +	.update_status	= lv5207lp_backlight_update_status,
> +	.get_brightness	= lv5207lp_backlight_get_brightness,
> +	.check_fb	= lv5207lp_backlight_check_fb,
> +};
> +
> +static int lv5207lp_probe(struct i2c_client *client,
> +			  const struct i2c_device_id *id)
> +{
> +	struct lv5207lp_platform_data *pdata = client->dev.platform_data;
> +	struct backlight_device *backlight;
> +	struct backlight_properties props;
> +	struct lv5207lp *lv;
> +
> +	if (pdata = NULL) {
> +		dev_err(&client->dev, "No platform data supplied\n");
> +		return -EINVAL;
> +	}
> +
> +	if (!i2c_check_functionality(client->adapter,
> +				     I2C_FUNC_SMBUS_BYTE_DATA)) {
> +		dev_warn(&client->dev,
> +			 "I2C adapter doesn't support I2C_FUNC_SMBUS_BYTE\n");
> +		return -EIO;
> +	}
> +
> +	lv = devm_kzalloc(&client->dev, sizeof(*lv), GFP_KERNEL);
> +	if (!lv)
> +		return -ENOMEM;
> +
> +	lv->client = client;
> +	lv->pdata = pdata;
> +
> +	memset(&props, 0, sizeof(props));
> +	props.type = BACKLIGHT_RAW;
> +	props.max_brightness = min_t(unsigned int, pdata->max_value,
> +				     LV5207LP_MAX_BRIGHTNESS);
> +	props.brightness = clamp_t(unsigned int, pdata->def_value, 0,
> +				   props.max_brightness);
> +
> +	backlight = backlight_device_register(dev_name(&client->dev),
> +					      &lv->client->dev, lv,
> +					      &lv5207lp_backlight_ops, &props);
> +	if (IS_ERR(backlight)) {
> +		dev_err(&client->dev, "failed to register backlight\n");
> +		return PTR_ERR(backlight);
> +	}
> +
> +	backlight_update_status(backlight);
> +	i2c_set_clientdata(client, backlight);
> +
> +	return 0;
> +}
> +
> +static int lv5207lp_remove(struct i2c_client *client)
> +{
> +	struct backlight_device *backlight = i2c_get_clientdata(client);
> +
> +	backlight->props.brightness = 0;
> +	backlight_update_status(backlight);
> +	backlight_device_unregister(backlight);
> +
> +	return 0;
> +}
> +
> +static const struct i2c_device_id lv5207lp_ids[] = {
> +	{ "lv5207lp", 0 },
> +	{ }
> +};
> +MODULE_DEVICE_TABLE(i2c, lv5207lp_ids);
> +
> +static struct i2c_driver lv5207lp_driver = {
> +	.driver = {
> +		.name = "lv5207lp",
> +	},
> +	.probe = lv5207lp_probe,
> +	.remove = lv5207lp_remove,
> +	.id_table = lv5207lp_ids,
> +};
> +
> +module_i2c_driver(lv5207lp_driver);
> +
> +MODULE_DESCRIPTION("Sanyo LV5207LP Backlight Driver");
> +MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>");
> +MODULE_LICENSE("GPL");
> diff --git a/include/linux/platform_data/lv5207lp.h b/include/linux/platform_data/lv5207lp.h
> new file mode 100644
> index 0000000..ac95cb1
> --- /dev/null
> +++ b/include/linux/platform_data/lv5207lp.h
> @@ -0,0 +1,20 @@
> +/*
> + * lv5207lp.h - Sanyo LV5207LP LEDs Driver
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +#ifndef __LV5207LP_H__
> +#define __LV5207LP_H__
> +
> +struct device;
> +
> +struct lv5207lp_platform_data {
> +	struct device *fbdev;
> +	unsigned int max_value;
> +	unsigned int def_value;
> +};
> +
> +#endif
> +
> --
> 1.7.8.6
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-fbdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


^ permalink raw reply

* [PATCHv15 7/7] drm_modes: add of_videomode helpers
From: Steffen Trumtrar @ 2012-11-26  9:07 UTC (permalink / raw)
  To: devicetree-discuss
  Cc: Steffen Trumtrar, Rob Herring, linux-fbdev, dri-devel,
	Laurent Pinchart, Thierry Reding, Guennady Liakhovetski,
	linux-media, Tomi Valkeinen, Stephen Warren, kernel,
	Florian Tobias Schandinat, David Airlie
In-Reply-To: <1353920848-1705-1-git-send-email-s.trumtrar@pengutronix.de>

Add helper to get drm_display_mode from devicetree.

Signed-off-by: Steffen Trumtrar <s.trumtrar@pengutronix.de>
Reviewed-by: Thierry Reding <thierry.reding@avionic-design.de>
Acked-by: Thierry Reding <thierry.reding@avionic-design.de>
Tested-by: Thierry Reding <thierry.reding@avionic-design.de>
Tested-by: Philipp Zabel <p.zabel@pengutronix.de>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/gpu/drm/drm_modes.c |   33 +++++++++++++++++++++++++++++++++
 include/drm/drmP.h          |    6 ++++++
 2 files changed, 39 insertions(+)

diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
index 8263ea1..3568f0a 100644
--- a/drivers/gpu/drm/drm_modes.c
+++ b/drivers/gpu/drm/drm_modes.c
@@ -33,6 +33,7 @@
 #include <linux/list.h>
 #include <linux/list_sort.h>
 #include <linux/export.h>
+#include <linux/of_videomode.h>
 #include <linux/videomode.h>
 #include <drm/drmP.h>
 #include <drm/drm_crtc.h>
@@ -541,6 +542,38 @@ int drm_display_mode_from_videomode(const struct videomode *vm,
 EXPORT_SYMBOL_GPL(drm_display_mode_from_videomode);
 #endif
 
+#if IS_ENABLED(CONFIG_OF_VIDEOMODE)
+/**
+ * of_get_drm_display_mode - get a drm_display_mode from devicetree
+ * @np: device_node with the timing specification
+ * @dmode: will be set to the return value
+ * @index: index into the list of display timings in devicetree
+ *
+ * This function is expensive and should only be used, if only one mode is to be
+ * read from DT. To get multiple modes start with of_get_display_timings and
+ * work with that instead.
+ */
+int of_get_drm_display_mode(struct device_node *np,
+			    struct drm_display_mode *dmode, int index)
+{
+	struct videomode vm;
+	int ret;
+
+	ret = of_get_videomode(np, &vm, index);
+	if (ret)
+		return ret;
+
+	drm_display_mode_from_videomode(&vm, dmode);
+
+	pr_info("%s: got %dx%d display mode from %s\n", __func__, vm.hactive,
+		vm.vactive, np->name);
+	drm_mode_debug_printmodeline(dmode);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(of_get_drm_display_mode);
+#endif
+
 /**
  * drm_mode_set_name - set the name on a mode
  * @mode: name will be set in this mode
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index 2194e97..1784e55 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -85,6 +85,7 @@ struct module;
 struct drm_file;
 struct drm_device;
 
+struct device_node;
 struct videomode;
 
 #include <drm/drm_os_linux.h>
@@ -1460,6 +1461,11 @@ drm_mode_create_from_cmdline_mode(struct drm_device *dev,
 extern int drm_display_mode_from_videomode(const struct videomode *vm,
 					   struct drm_display_mode *dmode);
 #endif
+#if IS_ENABLED(CONFIG_OF_VIDEOMODE)
+extern int of_get_drm_display_mode(struct device_node *np,
+				   struct drm_display_mode *dmode,
+				   int index);
+#endif
 
 /* Modesetting support */
 extern void drm_vblank_pre_modeset(struct drm_device *dev, int crtc);
-- 
1.7.10.4


^ permalink raw reply related

* [PATCHv15 6/7] drm_modes: add videomode helpers
From: Steffen Trumtrar @ 2012-11-26  9:07 UTC (permalink / raw)
  To: devicetree-discuss
  Cc: Steffen Trumtrar, Rob Herring, linux-fbdev, dri-devel,
	Laurent Pinchart, Thierry Reding, Guennady Liakhovetski,
	linux-media, Tomi Valkeinen, Stephen Warren, kernel,
	Florian Tobias Schandinat, David Airlie
In-Reply-To: <1353920848-1705-1-git-send-email-s.trumtrar@pengutronix.de>

Add conversion from videomode to drm_display_mode

Signed-off-by: Steffen Trumtrar <s.trumtrar@pengutronix.de>
Reviewed-by: Thierry Reding <thierry.reding@avionic-design.de>
Acked-by: Thierry Reding <thierry.reding@avionic-design.de>
Tested-by: Thierry Reding <thierry.reding@avionic-design.de>
Tested-by: Philipp Zabel <p.zabel@pengutronix.de>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Steffen Trumtrar <s.trumtrar@pengutronix.de>
---
 drivers/gpu/drm/drm_modes.c |   37 +++++++++++++++++++++++++++++++++++++
 include/drm/drmP.h          |    7 +++++++
 2 files changed, 44 insertions(+)

diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
index 59450f3..8263ea1 100644
--- a/drivers/gpu/drm/drm_modes.c
+++ b/drivers/gpu/drm/drm_modes.c
@@ -33,6 +33,7 @@
 #include <linux/list.h>
 #include <linux/list_sort.h>
 #include <linux/export.h>
+#include <linux/videomode.h>
 #include <drm/drmP.h>
 #include <drm/drm_crtc.h>
 
@@ -504,6 +505,42 @@ drm_gtf_mode(struct drm_device *dev, int hdisplay, int vdisplay, int vrefresh,
 }
 EXPORT_SYMBOL(drm_gtf_mode);
 
+#if IS_ENABLED(CONFIG_VIDEOMODE)
+int drm_display_mode_from_videomode(const struct videomode *vm,
+				    struct drm_display_mode *dmode)
+{
+	dmode->hdisplay = vm->hactive;
+	dmode->hsync_start = dmode->hdisplay + vm->hfront_porch;
+	dmode->hsync_end = dmode->hsync_start + vm->hsync_len;
+	dmode->htotal = dmode->hsync_end + vm->hback_porch;
+
+	dmode->vdisplay = vm->vactive;
+	dmode->vsync_start = dmode->vdisplay + vm->vfront_porch;
+	dmode->vsync_end = dmode->vsync_start + vm->vsync_len;
+	dmode->vtotal = dmode->vsync_end + vm->vback_porch;
+
+	dmode->clock = vm->pixelclock / 1000;
+
+	dmode->flags = 0;
+	if (vm->hah)
+		dmode->flags |= DRM_MODE_FLAG_PHSYNC;
+	else
+		dmode->flags |= DRM_MODE_FLAG_NHSYNC;
+	if (vm->vah)
+		dmode->flags |= DRM_MODE_FLAG_PVSYNC;
+	else
+		dmode->flags |= DRM_MODE_FLAG_NVSYNC;
+	if (vm->interlaced)
+		dmode->flags |= DRM_MODE_FLAG_INTERLACE;
+	if (vm->doublescan)
+		dmode->flags |= DRM_MODE_FLAG_DBLSCAN;
+	drm_mode_set_name(dmode);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(drm_display_mode_from_videomode);
+#endif
+
 /**
  * drm_mode_set_name - set the name on a mode
  * @mode: name will be set in this mode
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index 3fd8280..2194e97 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -85,6 +85,8 @@ struct module;
 struct drm_file;
 struct drm_device;
 
+struct videomode;
+
 #include <drm/drm_os_linux.h>
 #include <drm/drm_hashtab.h>
 #include <drm/drm_mm.h>
@@ -1454,6 +1456,11 @@ extern struct drm_display_mode *
 drm_mode_create_from_cmdline_mode(struct drm_device *dev,
 				  struct drm_cmdline_mode *cmd);
 
+#if IS_ENABLED(CONFIG_VIDEOMODE)
+extern int drm_display_mode_from_videomode(const struct videomode *vm,
+					   struct drm_display_mode *dmode);
+#endif
+
 /* Modesetting support */
 extern void drm_vblank_pre_modeset(struct drm_device *dev, int crtc);
 extern void drm_vblank_post_modeset(struct drm_device *dev, int crtc);
-- 
1.7.10.4


^ permalink raw reply related

* [PATCHv15 5/7] fbmon: add of_videomode helpers
From: Steffen Trumtrar @ 2012-11-26  9:07 UTC (permalink / raw)
  To: devicetree-discuss
  Cc: Steffen Trumtrar, Rob Herring, linux-fbdev, dri-devel,
	Laurent Pinchart, Thierry Reding, Guennady Liakhovetski,
	linux-media, Tomi Valkeinen, Stephen Warren, kernel,
	Florian Tobias Schandinat, David Airlie
In-Reply-To: <1353920848-1705-1-git-send-email-s.trumtrar@pengutronix.de>

Add helper to get fb_videomode from devicetree.

Signed-off-by: Steffen Trumtrar <s.trumtrar@pengutronix.de>
Reviewed-by: Thierry Reding <thierry.reding@avionic-design.de>
Acked-by: Thierry Reding <thierry.reding@avionic-design.de>
Tested-by: Thierry Reding <thierry.reding@avionic-design.de>
Tested-by: Philipp Zabel <p.zabel@pengutronix.de>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Steffen Trumtrar <s.trumtrar@pengutronix.de>
---
 drivers/video/fbmon.c |   42 ++++++++++++++++++++++++++++++++++++++++++
 include/linux/fb.h    |    6 ++++++
 2 files changed, 48 insertions(+)

diff --git a/drivers/video/fbmon.c b/drivers/video/fbmon.c
index 733553b..4a8484d 100644
--- a/drivers/video/fbmon.c
+++ b/drivers/video/fbmon.c
@@ -28,6 +28,7 @@
  */
 #include <linux/fb.h>
 #include <linux/module.h>
+#include <linux/of_videomode.h>
 #include <linux/pci.h>
 #include <linux/slab.h>
 #include <linux/videomode.h>
@@ -1424,6 +1425,47 @@ int fb_videomode_from_videomode(const struct videomode *vm,
 EXPORT_SYMBOL_GPL(fb_videomode_from_videomode);
 #endif
 
+#if IS_ENABLED(CONFIG_OF_VIDEOMODE)
+static inline void dump_fb_videomode(const struct fb_videomode *m)
+{
+	pr_debug("fb_videomode = %ux%u@%uHz (%ukHz) %u %u %u %u %u %u %u %u %u\n",
+		 m->xres, m->yres, m->refresh, m->pixclock, m->left_margin,
+		 m->right_margin, m->upper_margin, m->lower_margin,
+		 m->hsync_len, m->vsync_len, m->sync, m->vmode, m->flag);
+}
+
+/**
+ * of_get_fb_videomode - get a fb_videomode from devicetree
+ * @np: device_node with the timing specification
+ * @fb: will be set to the return value
+ * @index: index into the list of display timings in devicetree
+ *
+ * DESCRIPTION:
+ * This function is expensive and should only be used, if only one mode is to be
+ * read from DT. To get multiple modes start with of_get_display_timings ond
+ * work with that instead.
+ */
+int of_get_fb_videomode(struct device_node *np, struct fb_videomode *fb,
+			int index)
+{
+	struct videomode vm;
+	int ret;
+
+	ret = of_get_videomode(np, &vm, index);
+	if (ret)
+		return ret;
+
+	fb_videomode_from_videomode(&vm, fb);
+
+	pr_info("%s: got %dx%d display mode from %s\n", __func__, vm.hactive,
+		vm.vactive, np->name);
+	dump_fb_videomode(fb);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(of_get_fb_videomode);
+#endif
+
 #else
 int fb_parse_edid(unsigned char *edid, struct fb_var_screeninfo *var)
 {
diff --git a/include/linux/fb.h b/include/linux/fb.h
index 4404ec2..c2d933d 100644
--- a/include/linux/fb.h
+++ b/include/linux/fb.h
@@ -20,6 +20,7 @@ struct fb_info;
 struct device;
 struct file;
 struct videomode;
+struct device_node;
 
 /* Definitions below are used in the parsed monitor specs */
 #define FB_DPMS_ACTIVE_OFF	1
@@ -715,6 +716,11 @@ extern void fb_destroy_modedb(struct fb_videomode *modedb);
 extern int fb_find_mode_cvt(struct fb_videomode *mode, int margins, int rb);
 extern unsigned char *fb_ddc_read(struct i2c_adapter *adapter);
 
+#if IS_ENABLED(CONFIG_OF_VIDEOMODE)
+extern int of_get_fb_videomode(struct device_node *np,
+			       struct fb_videomode *fb,
+			       int index);
+#endif
 #if IS_ENABLED(CONFIG_VIDEOMODE)
 extern int fb_videomode_from_videomode(const struct videomode *vm,
 				       struct fb_videomode *fbmode);
-- 
1.7.10.4


^ permalink raw reply related

* [PATCHv15 4/7] fbmon: add videomode helpers
From: Steffen Trumtrar @ 2012-11-26  9:07 UTC (permalink / raw)
  To: devicetree-discuss
  Cc: Steffen Trumtrar, Rob Herring, linux-fbdev, dri-devel,
	Laurent Pinchart, Thierry Reding, Guennady Liakhovetski,
	linux-media, Tomi Valkeinen, Stephen Warren, kernel,
	Florian Tobias Schandinat, David Airlie
In-Reply-To: <1353920848-1705-1-git-send-email-s.trumtrar@pengutronix.de>

Add a function to convert from the generic videomode to a fb_videomode.

Signed-off-by: Steffen Trumtrar <s.trumtrar@pengutronix.de>
Reviewed-by: Thierry Reding <thierry.reding@avionic-design.de>
Acked-by: Thierry Reding <thierry.reding@avionic-design.de>
Tested-by: Thierry Reding <thierry.reding@avionic-design.de>
Tested-by: Philipp Zabel <p.zabel@pengutronix.de>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Steffen Trumtrar <s.trumtrar@pengutronix.de>
---
 drivers/video/fbmon.c |   51 +++++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/fb.h    |    6 ++++++
 2 files changed, 57 insertions(+)

diff --git a/drivers/video/fbmon.c b/drivers/video/fbmon.c
index cef6557..733553b 100644
--- a/drivers/video/fbmon.c
+++ b/drivers/video/fbmon.c
@@ -30,6 +30,7 @@
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/slab.h>
+#include <linux/videomode.h>
 #include <video/edid.h>
 #ifdef CONFIG_PPC_OF
 #include <asm/prom.h>
@@ -1373,6 +1374,56 @@ int fb_get_mode(int flags, u32 val, struct fb_var_screeninfo *var, struct fb_inf
 	kfree(timings);
 	return err;
 }
+
+#if IS_ENABLED(CONFIG_VIDEOMODE)
+int fb_videomode_from_videomode(const struct videomode *vm,
+				struct fb_videomode *fbmode)
+{
+	unsigned int htotal, vtotal;
+
+	fbmode->xres = vm->hactive;
+	fbmode->left_margin = vm->hback_porch;
+	fbmode->right_margin = vm->hfront_porch;
+	fbmode->hsync_len = vm->hsync_len;
+
+	fbmode->yres = vm->vactive;
+	fbmode->upper_margin = vm->vback_porch;
+	fbmode->lower_margin = vm->vfront_porch;
+	fbmode->vsync_len = vm->vsync_len;
+
+	/* prevent division by zero in KHZ2PICOS macro */
+	fbmode->pixclock = vm->pixelclock ? KHZ2PICOS(vm->pixelclock / 1000) : 0;
+
+	fbmode->sync = 0;
+	fbmode->vmode = 0;
+	if (vm->hah)
+		fbmode->sync |= FB_SYNC_HOR_HIGH_ACT;
+	if (vm->vah)
+		fbmode->sync |= FB_SYNC_VERT_HIGH_ACT;
+	if (vm->interlaced)
+		fbmode->vmode |= FB_VMODE_INTERLACED;
+	if (vm->doublescan)
+		fbmode->vmode |= FB_VMODE_DOUBLE;
+	fbmode->flag = 0;
+
+	htotal = vm->hactive + vm->hfront_porch + vm->hback_porch +
+		 vm->hsync_len;
+	vtotal = vm->vactive + vm->vfront_porch + vm->vback_porch +
+		 vm->vsync_len;
+	/* prevent division by zero */
+	if (htotal && vtotal)
+		fbmode->refresh = vm->pixelclock / (htotal * vtotal);
+	/* a mode must have htotal and vtotal != 0 or it is invalid */
+	else {
+		fbmode->refresh = 0;
+		return -EINVAL;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(fb_videomode_from_videomode);
+#endif
+
 #else
 int fb_parse_edid(unsigned char *edid, struct fb_var_screeninfo *var)
 {
diff --git a/include/linux/fb.h b/include/linux/fb.h
index c7a9571..4404ec2 100644
--- a/include/linux/fb.h
+++ b/include/linux/fb.h
@@ -19,6 +19,7 @@ struct vm_area_struct;
 struct fb_info;
 struct device;
 struct file;
+struct videomode;
 
 /* Definitions below are used in the parsed monitor specs */
 #define FB_DPMS_ACTIVE_OFF	1
@@ -714,6 +715,11 @@ extern void fb_destroy_modedb(struct fb_videomode *modedb);
 extern int fb_find_mode_cvt(struct fb_videomode *mode, int margins, int rb);
 extern unsigned char *fb_ddc_read(struct i2c_adapter *adapter);
 
+#if IS_ENABLED(CONFIG_VIDEOMODE)
+extern int fb_videomode_from_videomode(const struct videomode *vm,
+				       struct fb_videomode *fbmode);
+#endif
+
 /* drivers/video/modedb.c */
 #define VESA_MODEDB_SIZE 34
 extern void fb_var_to_videomode(struct fb_videomode *mode,
-- 
1.7.10.4


^ permalink raw reply related

* [PATCHv15 3/7] video: add of helper for display timings/videomode
From: Steffen Trumtrar @ 2012-11-26  9:07 UTC (permalink / raw)
  To: devicetree-discuss
  Cc: Steffen Trumtrar, Philipp Zabel, Rob Herring, linux-fbdev,
	dri-devel, Laurent Pinchart, Thierry Reding,
	Guennady Liakhovetski, linux-media, Tomi Valkeinen,
	Stephen Warren, kernel, Florian Tobias Schandinat, David Airlie
In-Reply-To: <1353920848-1705-1-git-send-email-s.trumtrar@pengutronix.de>

This adds support for reading display timings from DT into a struct
display_timings. The of_display_timing implementation supports multiple
subnodes. All children are read into an array, that can be queried.

If no native mode is specified, the first subnode will be used.

For cases where the graphics driver knows there can be only one
mode description or where the driver only supports one mode, a helper
function of_get_videomode is added, that gets a struct videomode from DT.

Signed-off-by: Steffen Trumtrar <s.trumtrar@pengutronix.de>
Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
Acked-by: Stephen Warren <swarren@nvidia.com>
Reviewed-by: Thierry Reding <thierry.reding@avionic-design.de>
Acked-by: Thierry Reding <thierry.reding@avionic-design.de>
Tested-by: Thierry Reding <thierry.reding@avionic-design.de>
Tested-by: Philipp Zabel <p.zabel@pengutronix.de>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 .../devicetree/bindings/video/display-timing.txt   |  107 ++++++++++
 drivers/video/Kconfig                              |   15 ++
 drivers/video/Makefile                             |    2 +
 drivers/video/of_display_timing.c                  |  219 ++++++++++++++++++++
 drivers/video/of_videomode.c                       |   54 +++++
 include/linux/of_display_timing.h                  |   20 ++
 include/linux/of_videomode.h                       |   18 ++
 7 files changed, 435 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/video/display-timing.txt
 create mode 100644 drivers/video/of_display_timing.c
 create mode 100644 drivers/video/of_videomode.c
 create mode 100644 include/linux/of_display_timing.h
 create mode 100644 include/linux/of_videomode.h

diff --git a/Documentation/devicetree/bindings/video/display-timing.txt b/Documentation/devicetree/bindings/video/display-timing.txt
new file mode 100644
index 0000000..e238f27
--- /dev/null
+++ b/Documentation/devicetree/bindings/video/display-timing.txt
@@ -0,0 +1,107 @@
+display-timing bindings
+===========+
+display-timings node
+--------------------
+
+required properties:
+ - none
+
+optional properties:
+ - native-mode: The native mode for the display, in case multiple modes are
+		provided. When omitted, assume the first node is the native.
+
+timing subnode
+--------------
+
+required properties:
+ - hactive, vactive: display resolution
+ - hfront-porch, hback-porch, hsync-len: horizontal display timing parameters
+   in pixels
+   vfront-porch, vback-porch, vsync-len: vertical display timing parameters in
+   lines
+ - clock-frequency: display clock in Hz
+
+optional properties:
+ - hsync-active: hsync pulse is active low/high/ignored
+ - vsync-active: vsync pulse is active low/high/ignored
+ - de-active: data-enable pulse is active low/high/ignored
+ - pixelclk-inverted: pixelclock is inverted (active on falling edge)/
+				non-inverted (active on rising edge)/
+				     ignored (ignore property)
+ - interlaced (bool): boolean to enable interlaced mode
+ - doublescan (bool): boolean to enable doublescan mode
+ - doubleclk (bool)
+
+All the optional properties that are not bool follow the following logic:
+    <1>: high active
+    <0>: low active
+    omitted: not used on hardware
+
+There are different ways of describing the capabilities of a display. The devicetree
+representation corresponds to the one commonly found in datasheets for displays.
+If a display supports multiple signal timings, the native-mode can be specified.
+
+The parameters are defined as
+
+  +----------+---------------------------------------------+----------+-------+
+  |          |                ↑                            |          |       |
+  |          |                |vback_porch                 |          |       |
+  |          |                ↓                            |          |       |
+  +----------###############################################----------+-------+
+  |          #                ↑                            #          |       |
+  |          #                |                            #          |       |
+  |  hback   #                |                            #  hfront  | hsync |
+  |   porch  #                |       hactive              #  porch   |  len  |
+  |<-------->#<---------------+--------------------------->#<-------->|<----->|
+  |          #                |                            #          |       |
+  |          #                |vactive                     #          |       |
+  |          #                |                            #          |       |
+  |          #                ↓                            #          |       |
+  +----------###############################################----------+-------+
+  |          |                ↑                            |          |       |
+  |          |                |vfront_porch                |          |       |
+  |          |                ↓                            |          |       |
+  +----------+---------------------------------------------+----------+-------+
+  |          |                ↑                            |          |       |
+  |          |                |vsync_len                   |          |       |
+  |          |                ↓                            |          |       |
+  +----------+---------------------------------------------+----------+-------+
+
+
+Example:
+
+	display-timings {
+		native-mode = <&timing0>;
+		timing0: 1080p24 {
+			/* 1920x1080p24 */
+			clock-frequency = <52000000>;
+			hactive = <1920>;
+			vactive = <1080>;
+			hfront-porch = <25>;
+			hback-porch = <25>;
+			hsync-len = <25>;
+			vback-porch = <2>;
+			vfront-porch = <2>;
+			vsync-len = <2>;
+			hsync-active = <1>;
+		};
+	};
+
+Every required property also supports the use of ranges, so the commonly used
+datasheet description with <min typ max>-tuples can be used.
+
+Example:
+
+	timing1: timing {
+		/* 1920x1080p24 */
+		clock-frequency = <148500000>;
+		hactive = <1920>;
+		vactive = <1080>;
+		hsync-len = <0 44 60>;
+		hfront-porch = <80 88 95>;
+		hback-porch = <100 148 160>;
+		vfront-porch = <0 4 6>;
+		vback-porch = <0 36 50>;
+		vsync-len = <0 5 6>;
+	};
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 2a23b18..c000f5a 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -39,6 +39,21 @@ config DISPLAY_TIMING
 config VIDEOMODE
        bool
 
+config OF_DISPLAY_TIMING
+	bool "Enable device tree display timing support"
+	depends on OF
+	select DISPLAY_TIMING
+	help
+	  helper to parse display timings from the devicetree
+
+config OF_VIDEOMODE
+	bool "Enable device tree videomode support"
+	depends on OF
+	select VIDEOMODE
+	select OF_DISPLAY_TIMING
+	help
+	  helper to get videomodes from the devicetree
+
 menuconfig FB
 	tristate "Support for frame buffer devices"
 	---help---
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index fc30439..b936b00 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -168,4 +168,6 @@ obj-$(CONFIG_FB_VIRTUAL)          += vfb.o
 #video output switch sysfs driver
 obj-$(CONFIG_VIDEO_OUTPUT_CONTROL) += output.o
 obj-$(CONFIG_DISPLAY_TIMING) += display_timing.o
+obj-$(CONFIG_OF_DISPLAY_TIMING) += of_display_timing.o
 obj-$(CONFIG_VIDEOMODE) += videomode.o
+obj-$(CONFIG_OF_VIDEOMODE) += of_videomode.o
diff --git a/drivers/video/of_display_timing.c b/drivers/video/of_display_timing.c
new file mode 100644
index 0000000..b6c549e
--- /dev/null
+++ b/drivers/video/of_display_timing.c
@@ -0,0 +1,219 @@
+/*
+ * OF helpers for parsing display timings
+ *
+ * Copyright (c) 2012 Steffen Trumtrar <s.trumtrar@pengutronix.de>, Pengutronix
+ *
+ * based on of_videomode.c by Sascha Hauer <s.hauer@pengutronix.de>
+ *
+ * This file is released under the GPLv2
+ */
+#include <linux/display_timing.h>
+#include <linux/export.h>
+#include <linux/of.h>
+#include <linux/of_display_timing.h>
+#include <linux/slab.h>
+
+/**
+ * parse_property - parse timing_entry from device_node
+ * @np: device_node with the property
+ * @name: name of the property
+ * @result: will be set to the return value
+ *
+ * DESCRIPTION:
+ * Every display_timing can be specified with either just the typical value or
+ * a range consisting of min/typ/max. This function helps handling this
+ **/
+static int parse_property(const struct device_node *np, const char *name,
+			  struct timing_entry *result)
+{
+	struct property *prop;
+	int length, cells, ret;
+
+	prop = of_find_property(np, name, &length);
+	if (!prop) {
+		pr_err("%s: could not find property %s\n", __func__, name);
+		return -EINVAL;
+	}
+
+	cells = length / sizeof(u32);
+	if (cells = 1) {
+		ret = of_property_read_u32(np, name, &result->typ);
+		result->min = result->typ;
+		result->max = result->typ;
+	} else if (cells = 3) {
+		ret = of_property_read_u32_array(np, name, &result->min, cells);
+	} else {
+		pr_err("%s: illegal timing specification in %s\n", __func__,
+			name);
+		return -EINVAL;
+	}
+
+	return ret;
+}
+
+/**
+ * of_get_display_timing - parse display_timing entry from device_node
+ * @np: device_node with the properties
+ **/
+static struct display_timing *of_get_display_timing(const struct device_node
+						    *np)
+{
+	struct display_timing *dt;
+	int ret = 0;
+
+	dt = kzalloc(sizeof(*dt), GFP_KERNEL);
+	if (!dt) {
+		pr_err("%s: could not allocate display_timing struct\n",
+			__func__);
+		return NULL;
+	}
+
+	ret |= parse_property(np, "hback-porch", &dt->hback_porch);
+	ret |= parse_property(np, "hfront-porch", &dt->hfront_porch);
+	ret |= parse_property(np, "hactive", &dt->hactive);
+	ret |= parse_property(np, "hsync-len", &dt->hsync_len);
+	ret |= parse_property(np, "vback-porch", &dt->vback_porch);
+	ret |= parse_property(np, "vfront-porch", &dt->vfront_porch);
+	ret |= parse_property(np, "vactive", &dt->vactive);
+	ret |= parse_property(np, "vsync-len", &dt->vsync_len);
+	ret |= parse_property(np, "clock-frequency", &dt->pixelclock);
+
+	of_property_read_u32(np, "vsync-active", &dt->vsync_pol_active);
+	of_property_read_u32(np, "hsync-active", &dt->hsync_pol_active);
+	of_property_read_u32(np, "de-active", &dt->de_pol_active);
+	of_property_read_u32(np, "pixelclk-inverted", &dt->pixelclk_pol);
+	dt->interlaced = of_property_read_bool(np, "interlaced");
+	dt->doublescan = of_property_read_bool(np, "doublescan");
+
+	if (ret) {
+		pr_err("%s: error reading timing properties\n", __func__);
+		kfree(dt);
+		return NULL;
+	}
+
+	return dt;
+}
+
+/**
+ * of_get_display_timings - parse all display_timing entries from a device_node
+ * @np: device_node with the subnodes
+ **/
+struct display_timings *of_get_display_timings(struct device_node *np)
+{
+	struct device_node *timings_np;
+	struct device_node *entry;
+	struct device_node *native_mode;
+	struct display_timings *disp;
+
+	if (!np) {
+		pr_err("%s: no devicenode given\n", __func__);
+		return NULL;
+	}
+
+	timings_np = of_find_node_by_name(np, "display-timings");
+	if (!timings_np) {
+		pr_err("%s: could not find display-timings node\n", __func__);
+		return NULL;
+	}
+
+	disp = kzalloc(sizeof(*disp), GFP_KERNEL);
+	if (!disp) {
+		pr_err("%s: could not allocate struct disp'\n", __func__);
+		goto dispfail;
+	}
+
+	entry = of_parse_phandle(timings_np, "native-mode", 0);
+	/* assume first child as native mode if none provided */
+	if (!entry)
+		entry = of_get_next_child(np, NULL);
+	/* if there is no child, it is useless to go on */
+	if (!entry) {
+		pr_err("%s: no timing specifications given\n", __func__);
+		goto entryfail;
+	}
+
+	pr_info("%s: using %s as default timing\n", __func__, entry->name);
+
+	native_mode = entry;
+
+	disp->num_timings = of_get_child_count(timings_np);
+	if (disp->num_timings = 0) {
+		/* should never happen, as entry was already found above */
+		pr_err("%s: no timings specified\n", __func__);
+		goto entryfail;
+	}
+
+	disp->timings = kzalloc(sizeof(struct display_timing *) * disp->num_timings,
+				GFP_KERNEL);
+	if (!disp->timings) {
+		pr_err("%s: could not allocate timings array\n", __func__);
+		goto entryfail;
+	}
+
+	disp->num_timings = 0;
+	disp->native_mode = 0;
+
+	for_each_child_of_node(timings_np, entry) {
+		struct display_timing *dt;
+
+		dt = of_get_display_timing(entry);
+		if (!dt) {
+			/*
+			 * to not encourage wrong devicetrees, fail in case of
+			 * an error
+			 */
+			pr_err("%s: error in timing %d\n", __func__,
+			       disp->num_timings + 1);
+			goto timingfail;
+		}
+
+		if (native_mode = entry)
+			disp->native_mode = disp->num_timings;
+
+		disp->timings[disp->num_timings] = dt;
+		disp->num_timings++;
+	}
+	of_node_put(timings_np);
+	/*
+	 * native_mode points to the device_node returned by of_parse_phandle
+	 * therefore call of_node_put on it
+	 */
+	of_node_put(native_mode);
+
+	pr_info("%s: got %d timings. Using timing #%d as default\n",
+		__func__, disp->num_timings, disp->native_mode + 1);
+
+	return disp;
+
+timingfail:
+	if (native_mode)
+		of_node_put(native_mode);
+	display_timings_release(disp);
+entryfail:
+	if (disp)
+		kfree(disp);
+dispfail:
+	of_node_put(timings_np);
+	return NULL;
+}
+EXPORT_SYMBOL_GPL(of_get_display_timings);
+
+/**
+ * of_display_timings_exists - check if a display-timings node is provided
+ * @np: device_node with the timing
+ **/
+int of_display_timings_exists(struct device_node *np)
+{
+	struct device_node *timings_np;
+
+	if (!np)
+		return -EINVAL;
+
+	timings_np = of_parse_phandle(np, "display-timings", 0);
+	if (!timings_np)
+		return -EINVAL;
+
+	of_node_put(timings_np);
+	return 1;
+}
+EXPORT_SYMBOL_GPL(of_display_timings_exists);
diff --git a/drivers/video/of_videomode.c b/drivers/video/of_videomode.c
new file mode 100644
index 0000000..38d4a64
--- /dev/null
+++ b/drivers/video/of_videomode.c
@@ -0,0 +1,54 @@
+/*
+ * generic videomode helper
+ *
+ * Copyright (c) 2012 Steffen Trumtrar <s.trumtrar@pengutronix.de>, Pengutronix
+ *
+ * This file is released under the GPLv2
+ */
+#include <linux/display_timing.h>
+#include <linux/errno.h>
+#include <linux/export.h>
+#include <linux/of.h>
+#include <linux/of_display_timing.h>
+#include <linux/of_videomode.h>
+#include <linux/videomode.h>
+
+/**
+ * of_get_videomode - get the videomode #<index> from devicetree
+ * @np - devicenode with the display_timings
+ * @vm - set to return value
+ * @index - index into list of display_timings
+ *	    (Set this to OF_USE_NATIVE_MODE to use whatever mode is
+ *	     specified as native mode in the DT.)
+ *
+ * DESCRIPTION:
+ * Get a list of all display timings and put the one
+ * specified by index into *vm. This function should only be used, if
+ * only one videomode is to be retrieved. A driver that needs to work
+ * with multiple/all videomodes should work with
+ * of_get_display_timings instead.
+ **/
+int of_get_videomode(struct device_node *np, struct videomode *vm,
+		     int index)
+{
+	struct display_timings *disp;
+	int ret;
+
+	disp = of_get_display_timings(np);
+	if (!disp) {
+		pr_err("%s: no timings specified\n", __func__);
+		return -EINVAL;
+	}
+
+	if (index = OF_USE_NATIVE_MODE)
+		index = disp->native_mode;
+
+	ret = videomode_from_timing(disp, vm, index);
+	if (ret)
+		return ret;
+
+	display_timings_release(disp);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(of_get_videomode);
diff --git a/include/linux/of_display_timing.h b/include/linux/of_display_timing.h
new file mode 100644
index 0000000..31e9695
--- /dev/null
+++ b/include/linux/of_display_timing.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2012 Steffen Trumtrar <s.trumtrar@pengutronix.de>
+ *
+ * display timings of helpers
+ *
+ * This file is released under the GPLv2
+ */
+
+#ifndef __LINUX_OF_DISPLAY_TIMING_H
+#define __LINUX_OF_DISPLAY_TIMING_H
+
+struct device_node;
+struct display_timings;
+
+#define OF_USE_NATIVE_MODE -1
+
+struct display_timings *of_get_display_timings(struct device_node *np);
+int of_display_timings_exists(struct device_node *np);
+
+#endif
diff --git a/include/linux/of_videomode.h b/include/linux/of_videomode.h
new file mode 100644
index 0000000..a07efcc
--- /dev/null
+++ b/include/linux/of_videomode.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright 2012 Steffen Trumtrar <s.trumtrar@pengutronix.de>
+ *
+ * videomode of-helpers
+ *
+ * This file is released under the GPLv2
+ */
+
+#ifndef __LINUX_OF_VIDEOMODE_H
+#define __LINUX_OF_VIDEOMODE_H
+
+struct device_node;
+struct videomode;
+
+int of_get_videomode(struct device_node *np, struct videomode *vm,
+		     int index);
+
+#endif /* __LINUX_OF_VIDEOMODE_H */
-- 
1.7.10.4


^ permalink raw reply related

* [PATCHv15 2/7] video: add display_timing and videomode
From: Steffen Trumtrar @ 2012-11-26  9:07 UTC (permalink / raw)
  To: devicetree-discuss
  Cc: Steffen Trumtrar, Rob Herring, linux-fbdev, dri-devel,
	Laurent Pinchart, Thierry Reding, Guennady Liakhovetski,
	linux-media, Tomi Valkeinen, Stephen Warren, kernel,
	Florian Tobias Schandinat, David Airlie
In-Reply-To: <1353920848-1705-1-git-send-email-s.trumtrar@pengutronix.de>

Add display_timing structure and the according helper functions. This allows
the description of a display via its supported timing parameters.

Also, add helper functions to convert from display timings to a generic videomode
structure.

The struct display_timing specifies all needed parameters to describe the signal
properties of a display in one mode. This includes
	- ranges for signals that may have min-, max- and typical values
	- single integers for signals that can be on, off or are ignored
	- booleans for signals that are either on or off

As a display may support multiple modes like this, a struct display_timings is
added, that holds all given struct display_timing pointers and declares the
native mode of the display.

Although a display may state that a signal can be in a range, it is driven with
fixed values that indicate a videomode. Therefore graphic drivers don't need all
the information of struct display_timing, but would generate a videomode from
the given set of supported signal timings and work with that.

The video subsystems all define their own structs that describe a mode and work
with that (e.g. fb_videomode or drm_display_mode). To slowly replace all those
various structures and allow code reuse across those subsystems, add struct
videomode as a generic description.

This patch only includes the most basic fields in struct videomode. All missing
fields that are needed to have a really generic video mode description can be
added at a later stage.

Signed-off-by: Steffen Trumtrar <s.trumtrar@pengutronix.de>
Reviewed-by: Thierry Reding <thierry.reding@avionic-design.de>
Acked-by: Thierry Reding <thierry.reding@avionic-design.de>
Tested-by: Thierry Reding <thierry.reding@avionic-design.de>
Tested-by: Philipp Zabel <p.zabel@pengutronix.de>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/video/Kconfig          |    6 +++
 drivers/video/Makefile         |    2 +
 drivers/video/display_timing.c |   24 ++++++++++
 drivers/video/videomode.c      |   44 +++++++++++++++++
 include/linux/display_timing.h |  104 ++++++++++++++++++++++++++++++++++++++++
 include/linux/videomode.h      |   54 +++++++++++++++++++++
 6 files changed, 234 insertions(+)
 create mode 100644 drivers/video/display_timing.c
 create mode 100644 drivers/video/videomode.c
 create mode 100644 include/linux/display_timing.h
 create mode 100644 include/linux/videomode.h

diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index d08d799..2a23b18 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -33,6 +33,12 @@ config VIDEO_OUTPUT_CONTROL
 	  This framework adds support for low-level control of the video 
 	  output switch.
 
+config DISPLAY_TIMING
+       bool
+
+config VIDEOMODE
+       bool
+
 menuconfig FB
 	tristate "Support for frame buffer devices"
 	---help---
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 23e948e..fc30439 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -167,3 +167,5 @@ obj-$(CONFIG_FB_VIRTUAL)          += vfb.o
 
 #video output switch sysfs driver
 obj-$(CONFIG_VIDEO_OUTPUT_CONTROL) += output.o
+obj-$(CONFIG_DISPLAY_TIMING) += display_timing.o
+obj-$(CONFIG_VIDEOMODE) += videomode.o
diff --git a/drivers/video/display_timing.c b/drivers/video/display_timing.c
new file mode 100644
index 0000000..ac9bbbc
--- /dev/null
+++ b/drivers/video/display_timing.c
@@ -0,0 +1,24 @@
+/*
+ * generic display timing functions
+ *
+ * Copyright (c) 2012 Steffen Trumtrar <s.trumtrar@pengutronix.de>, Pengutronix
+ *
+ * This file is released under the GPLv2
+ */
+
+#include <linux/display_timing.h>
+#include <linux/export.h>
+#include <linux/slab.h>
+
+void display_timings_release(struct display_timings *disp)
+{
+	if (disp->timings) {
+		unsigned int i;
+
+		for (i = 0; i < disp->num_timings; i++)
+			kfree(disp->timings[i]);
+		kfree(disp->timings);
+	}
+	kfree(disp);
+}
+EXPORT_SYMBOL_GPL(display_timings_release);
diff --git a/drivers/video/videomode.c b/drivers/video/videomode.c
new file mode 100644
index 0000000..784eaad
--- /dev/null
+++ b/drivers/video/videomode.c
@@ -0,0 +1,44 @@
+/*
+ * generic display timing functions
+ *
+ * Copyright (c) 2012 Steffen Trumtrar <s.trumtrar@pengutronix.de>, Pengutronix
+ *
+ * This file is released under the GPLv2
+ */
+
+#include <linux/display_timing.h>
+#include <linux/errno.h>
+#include <linux/export.h>
+#include <linux/videomode.h>
+
+int videomode_from_timing(const struct display_timings *disp,
+			  struct videomode *vm, unsigned int index)
+{
+	struct display_timing *dt;
+
+	dt = display_timings_get(disp, index);
+	if (!dt)
+		return -EINVAL;
+
+	vm->pixelclock = display_timing_get_value(&dt->pixelclock, TE_TYP);
+	vm->hactive = display_timing_get_value(&dt->hactive, TE_TYP);
+	vm->hfront_porch = display_timing_get_value(&dt->hfront_porch, TE_TYP);
+	vm->hback_porch = display_timing_get_value(&dt->hback_porch, TE_TYP);
+	vm->hsync_len = display_timing_get_value(&dt->hsync_len, TE_TYP);
+
+	vm->vactive = display_timing_get_value(&dt->vactive, TE_TYP);
+	vm->vfront_porch = display_timing_get_value(&dt->vfront_porch, TE_TYP);
+	vm->vback_porch = display_timing_get_value(&dt->vback_porch, TE_TYP);
+	vm->vsync_len = display_timing_get_value(&dt->vsync_len, TE_TYP);
+
+	vm->vah = dt->vsync_pol_active;
+	vm->hah = dt->hsync_pol_active;
+	vm->de = dt->de_pol_active;
+	vm->pixelclk_pol = dt->pixelclk_pol;
+
+	vm->interlaced = dt->interlaced;
+	vm->doublescan = dt->doublescan;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(videomode_from_timing);
diff --git a/include/linux/display_timing.h b/include/linux/display_timing.h
new file mode 100644
index 0000000..4986364
--- /dev/null
+++ b/include/linux/display_timing.h
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2012 Steffen Trumtrar <s.trumtrar@pengutronix.de>
+ *
+ * description of display timings
+ *
+ * This file is released under the GPLv2
+ */
+
+#ifndef __LINUX_DISPLAY_TIMING_H
+#define __LINUX_DISPLAY_TIMING_H
+
+#include <linux/types.h>
+
+/*
+ * A single signal can be specified via a range with a typical value, that lies
+ * somewhere inbetween. Do not use an array, to prevent any confusion about the
+ * meaning of every entry.
+ */
+struct timing_entry {
+	u32 min;
+	u32 typ;
+	u32 max;
+};
+
+enum timing_entry_index {
+	TE_MIN = 0,
+	TE_TYP = 1,
+	TE_MAX = 2,
+};
+
+/*
+ * Single "mode" entry. This describes one set of signal timings a display can
+ * have in one setting. This struct can later be converted to struct videomode
+ * (see include/linux/videomode.h). As each timing_entry can be defined as a
+ * range, one struct display_timing may become multiple struct videomodes.
+ */
+struct display_timing {
+	struct timing_entry pixelclock;
+
+	struct timing_entry hactive;
+	struct timing_entry hfront_porch;
+	struct timing_entry hback_porch;
+	struct timing_entry hsync_len;
+
+	struct timing_entry vactive;
+	struct timing_entry vfront_porch;
+	struct timing_entry vback_porch;
+	struct timing_entry vsync_len;
+
+	unsigned int vsync_pol_active;
+	unsigned int hsync_pol_active;
+	unsigned int de_pol_active;
+	unsigned int pixelclk_pol;
+	bool interlaced;
+	bool doublescan;
+};
+
+/*
+ * This describes all timing settings a display provides.
+ * The native_mode is the default setting for this display. It can be specified
+ * in the devicetree or will be the first that is provided. Drivers that can
+ * handle multiple videomode should work with this struct and convert each entry
+ * to the desired end result.
+ */
+struct display_timings {
+	unsigned int num_timings;
+	unsigned int native_mode;
+
+	struct display_timing **timings;
+};
+
+/* get value specified by index from struct timing_entry */
+static inline u32 display_timing_get_value(const struct timing_entry *te,
+					   enum timing_entry_index index)
+{
+	switch (index) {
+	case TE_MIN:
+		return te->min;
+		break;
+	case TE_TYP:
+		return te->typ;
+		break;
+	case TE_MAX:
+		return te->max;
+		break;
+	default:
+		return te->typ;
+	}
+}
+
+/* get one entry from struct display_timings */
+static inline struct display_timing *display_timings_get(const struct
+							 display_timings *disp,
+							 unsigned int index)
+{
+	if (disp->num_timings > index)
+		return disp->timings[index];
+	else
+		return NULL;
+}
+
+void display_timings_release(struct display_timings *disp);
+
+#endif
diff --git a/include/linux/videomode.h b/include/linux/videomode.h
new file mode 100644
index 0000000..562f490
--- /dev/null
+++ b/include/linux/videomode.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2012 Steffen Trumtrar <s.trumtrar@pengutronix.de>
+ *
+ * generic videomode description
+ *
+ * This file is released under the GPLv2
+ */
+
+#ifndef __LINUX_VIDEOMODE_H
+#define __LINUX_VIDEOMODE_H
+
+#include <linux/types.h>
+
+struct display_timings;
+
+/*
+ * Subsystem independent description of a videomode.
+ * Can be generated from struct display_timing.
+ */
+struct videomode {
+	u32 pixelclock;		/* pixelclock in Hz */
+
+	u32 hactive;
+	u32 hfront_porch;
+	u32 hback_porch;
+	u32 hsync_len;
+
+	u32 vactive;
+	u32 vfront_porch;
+	u32 vback_porch;
+	u32 vsync_len;
+
+	u32 hah;		/* hsync active high */
+	u32 vah;		/* vsync active high */
+	u32 de;			/* data enable */
+	u32 pixelclk_pol;
+
+	bool interlaced;
+	bool doublescan;
+};
+
+/**
+ * videomode_from_timing - convert display timing to videomode
+ * @disp: structure with all possible timing entries
+ * @vm: return value
+ * @index: index into the list of display timings in devicetree
+ *
+ * DESCRIPTION:
+ * This function converts a struct display_timing to a struct videomode.
+ */
+int videomode_from_timing(const struct display_timings *disp,
+			  struct videomode *vm, unsigned int index);
+
+#endif
-- 
1.7.10.4


^ permalink raw reply related

* [PATCHv15 1/7] viafb: rename display_timing to via_display_timing
From: Steffen Trumtrar @ 2012-11-26  9:07 UTC (permalink / raw)
  To: devicetree-discuss
  Cc: Steffen Trumtrar, Rob Herring, linux-fbdev, dri-devel,
	Laurent Pinchart, Thierry Reding, Guennady Liakhovetski,
	linux-media, Tomi Valkeinen, Stephen Warren, kernel,
	Florian Tobias Schandinat, David Airlie
In-Reply-To: <1353920848-1705-1-git-send-email-s.trumtrar@pengutronix.de>

The struct display_timing is specific to the via subsystem. The naming leads to
collisions with the new struct display_timing, that is supposed to be a shared
struct between different subsystems.
To clean this up, prepend the existing struct with the subsystem it is specific
to.

Signed-off-by: Steffen Trumtrar <s.trumtrar@pengutronix.de>
---
 drivers/video/via/hw.c              |    6 +++---
 drivers/video/via/hw.h              |    2 +-
 drivers/video/via/lcd.c             |    2 +-
 drivers/video/via/share.h           |    2 +-
 drivers/video/via/via_modesetting.c |    8 ++++----
 drivers/video/via/via_modesetting.h |    6 +++---
 6 files changed, 13 insertions(+), 13 deletions(-)

diff --git a/drivers/video/via/hw.c b/drivers/video/via/hw.c
index 898590d..5563c67 100644
--- a/drivers/video/via/hw.c
+++ b/drivers/video/via/hw.c
@@ -1467,10 +1467,10 @@ void viafb_set_vclock(u32 clk, int set_iga)
 	via_write_misc_reg_mask(0x0C, 0x0C); /* select external clock */
 }
 
-struct display_timing var_to_timing(const struct fb_var_screeninfo *var,
+struct via_display_timing var_to_timing(const struct fb_var_screeninfo *var,
 	u16 cxres, u16 cyres)
 {
-	struct display_timing timing;
+	struct via_display_timing timing;
 	u16 dx = (var->xres - cxres) / 2, dy = (var->yres - cyres) / 2;
 
 	timing.hor_addr = cxres;
@@ -1491,7 +1491,7 @@ struct display_timing var_to_timing(const struct fb_var_screeninfo *var,
 void viafb_fill_crtc_timing(const struct fb_var_screeninfo *var,
 	u16 cxres, u16 cyres, int iga)
 {
-	struct display_timing crt_reg = var_to_timing(var,
+	struct via_display_timing crt_reg = var_to_timing(var,
 		cxres ? cxres : var->xres, cyres ? cyres : var->yres);
 
 	if (iga = IGA1)
diff --git a/drivers/video/via/hw.h b/drivers/video/via/hw.h
index 6be243c..c3f2572 100644
--- a/drivers/video/via/hw.h
+++ b/drivers/video/via/hw.h
@@ -637,7 +637,7 @@ extern int viafb_LCD_ON;
 extern int viafb_DVI_ON;
 extern int viafb_hotplug;
 
-struct display_timing var_to_timing(const struct fb_var_screeninfo *var,
+struct via_display_timing var_to_timing(const struct fb_var_screeninfo *var,
 	u16 cxres, u16 cyres);
 void viafb_fill_crtc_timing(const struct fb_var_screeninfo *var,
 	u16 cxres, u16 cyres, int iga);
diff --git a/drivers/video/via/lcd.c b/drivers/video/via/lcd.c
index 1650379..022b0df 100644
--- a/drivers/video/via/lcd.c
+++ b/drivers/video/via/lcd.c
@@ -549,7 +549,7 @@ void viafb_lcd_set_mode(const struct fb_var_screeninfo *var, u16 cxres,
 	int panel_hres = plvds_setting_info->lcd_panel_hres;
 	int panel_vres = plvds_setting_info->lcd_panel_vres;
 	u32 clock;
-	struct display_timing timing;
+	struct via_display_timing timing;
 	struct fb_var_screeninfo panel_var;
 	const struct fb_videomode *mode_crt_table, *panel_crt_table;
 
diff --git a/drivers/video/via/share.h b/drivers/video/via/share.h
index 3158dfc..65c65c6 100644
--- a/drivers/video/via/share.h
+++ b/drivers/video/via/share.h
@@ -319,7 +319,7 @@ struct crt_mode_table {
 	int refresh_rate;
 	int h_sync_polarity;
 	int v_sync_polarity;
-	struct display_timing crtc;
+	struct via_display_timing crtc;
 };
 
 struct io_reg {
diff --git a/drivers/video/via/via_modesetting.c b/drivers/video/via/via_modesetting.c
index 0e431ae..0b414b0 100644
--- a/drivers/video/via/via_modesetting.c
+++ b/drivers/video/via/via_modesetting.c
@@ -30,9 +30,9 @@
 #include "debug.h"
 
 
-void via_set_primary_timing(const struct display_timing *timing)
+void via_set_primary_timing(const struct via_display_timing *timing)
 {
-	struct display_timing raw;
+	struct via_display_timing raw;
 
 	raw.hor_total = timing->hor_total / 8 - 5;
 	raw.hor_addr = timing->hor_addr / 8 - 1;
@@ -88,9 +88,9 @@ void via_set_primary_timing(const struct display_timing *timing)
 	via_write_reg_mask(VIACR, 0x17, 0x80, 0x80);
 }
 
-void via_set_secondary_timing(const struct display_timing *timing)
+void via_set_secondary_timing(const struct via_display_timing *timing)
 {
-	struct display_timing raw;
+	struct via_display_timing raw;
 
 	raw.hor_total = timing->hor_total - 1;
 	raw.hor_addr = timing->hor_addr - 1;
diff --git a/drivers/video/via/via_modesetting.h b/drivers/video/via/via_modesetting.h
index 06e09fe..f6a6503 100644
--- a/drivers/video/via/via_modesetting.h
+++ b/drivers/video/via/via_modesetting.h
@@ -33,7 +33,7 @@
 #define VIA_PITCH_MAX	0x3FF8
 
 
-struct display_timing {
+struct via_display_timing {
 	u16 hor_total;
 	u16 hor_addr;
 	u16 hor_blank_start;
@@ -49,8 +49,8 @@ struct display_timing {
 };
 
 
-void via_set_primary_timing(const struct display_timing *timing);
-void via_set_secondary_timing(const struct display_timing *timing);
+void via_set_primary_timing(const struct via_display_timing *timing);
+void via_set_secondary_timing(const struct via_display_timing *timing);
 void via_set_primary_address(u32 addr);
 void via_set_secondary_address(u32 addr);
 void via_set_primary_pitch(u32 pitch);
-- 
1.7.10.4


^ permalink raw reply related

* [PATCHv15 0/7] of: add display helper
From: Steffen Trumtrar @ 2012-11-26  9:07 UTC (permalink / raw)
  To: devicetree-discuss
  Cc: Steffen Trumtrar, Rob Herring, linux-fbdev, dri-devel,
	Laurent Pinchart, Thierry Reding, Guennady Liakhovetski,
	linux-media, Tomi Valkeinen, Stephen Warren, kernel,
	Florian Tobias Schandinat, David Airlie

Hi!

Changes since v14:
	- fix "const struct *" warning
		(reported by: Leela Krishna Amudala <l.krishna@samsung.com>)
	- return -EINVAL when htotal or vtotal are zero
	- remove unreachable code in of_get_display_timings
	- include headers in .c files and not implicit in .h
	- sort includes alphabetically
	- fix lower/uppercase in binding documentation
	- rebase onto v3.7-rc7

Changes since v13:
	- fix "const struct *" warning
		(reported by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>)
	- prevent division by zero in fb_videomode_from_videomode

Changes since v12:
	- rename struct display_timing to via_display_timing in via subsystem
	- fix refreshrate calculation
	- fix "const struct *" warnings
		(reported by: Manjunathappa, Prakash <prakash.pm@ti.com>)
	- some CodingStyle fixes
	- rewrite parts of commit messages and display-timings.txt
	- let display_timing_get_value get all values instead of just typical

Changes since v11:
	- make pointers const where applicable
	- add reviewed-by Laurent Pinchart

Changes since v10:
	- fix function name (drm_)display_mode_from_videomode
	- add acked-by, reviewed-by, tested-by

Changes since v9:
	- don't leak memory when previous timings were correct
	- CodingStyle fixes
	- move blank lines around

Changes since v8:
	- fix memory leaks
	- change API to be more consistent (foo_from_bar(struct bar, struct foo))
	- include headers were necessary
	- misc minor bufixe

Changes since v7:
	- move of_xxx to drivers/video
	- remove non-binding documentation from display-timings.txt
	- squash display_timings and videomode in one patch
	- misc minor fixes

Changes since v6:
	- get rid of some empty lines etc.
	- move functions to their subsystems
	- split of_ from non-of_ functions
	- add at least some kerneldoc to some functions

Changes since v5:
	- removed all display stuff and just describe timings

Changes since v4:
	- refactored functions

Changes since v3:
	- print error messages
	- free alloced memory
	- general cleanup

Changes since v2:
	- use hardware-near property-names
	- provide a videomode structure
	- allow ranges for all properties (<min,typ,max>)
	- functions to get display_mode or fb_videomode


Steffen Trumtrar (7):
  viafb: rename display_timing to via_display_timing
  video: add display_timing and videomode
  video: add of helper for display timings/videomode
  fbmon: add videomode helpers
  fbmon: add of_videomode helpers
  drm_modes: add videomode helpers
  drm_modes: add of_videomode helpers

 .../devicetree/bindings/video/display-timing.txt   |  107 ++++++++++
 drivers/gpu/drm/drm_modes.c                        |   70 +++++++
 drivers/video/Kconfig                              |   21 ++
 drivers/video/Makefile                             |    4 +
 drivers/video/display_timing.c                     |   24 +++
 drivers/video/fbmon.c                              |   93 +++++++++
 drivers/video/of_display_timing.c                  |  219 ++++++++++++++++++++
 drivers/video/of_videomode.c                       |   54 +++++
 drivers/video/via/hw.c                             |    6 +-
 drivers/video/via/hw.h                             |    2 +-
 drivers/video/via/lcd.c                            |    2 +-
 drivers/video/via/share.h                          |    2 +-
 drivers/video/via/via_modesetting.c                |    8 +-
 drivers/video/via/via_modesetting.h                |    6 +-
 drivers/video/videomode.c                          |   44 ++++
 include/drm/drmP.h                                 |   13 ++
 include/linux/display_timing.h                     |  104 ++++++++++
 include/linux/fb.h                                 |   12 ++
 include/linux/of_display_timing.h                  |   20 ++
 include/linux/of_videomode.h                       |   18 ++
 include/linux/videomode.h                          |   54 +++++
 21 files changed, 870 insertions(+), 13 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/video/display-timing.txt
 create mode 100644 drivers/video/display_timing.c
 create mode 100644 drivers/video/of_display_timing.c
 create mode 100644 drivers/video/of_videomode.c
 create mode 100644 drivers/video/videomode.c
 create mode 100644 include/linux/display_timing.h
 create mode 100644 include/linux/of_display_timing.h
 create mode 100644 include/linux/of_videomode.h
 create mode 100644 include/linux/videomode.h

-- 
1.7.10.4


^ permalink raw reply

* Re: [PATCH 11/24] MAINTAINERS: fix .../plat-mxc/include/mach/imxfb.h
From: Sascha Hauer @ 2012-11-26  8:46 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1353716808-16375-12-git-send-email-cesarb@cesarb.net>

On Fri, Nov 23, 2012 at 10:26:35PM -0200, Cesar Eduardo Barros wrote:
> This file was moved to include/linux/platform_data/video-imxfb.h by
> commit 82906b1 (ARM: imx: move platform_data definitions).
> 
> Cc: Sascha Hauer <kernel@pengutronix.de>
> Cc: linux-fbdev@vger.kernel.org
> Cc: linux-arm-kernel@lists.infradead.org
> Signed-off-by: Cesar Eduardo Barros <cesarb@cesarb.net>

Acked-by: Sascha Hauer <s.hauer@pengutronix.de>

Sascha

> ---
>  MAINTAINERS | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index a67a67a..887d717 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -3137,7 +3137,7 @@ M:	Sascha Hauer <kernel@pengutronix.de>
>  L:	linux-fbdev@vger.kernel.org
>  L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
>  S:	Maintained
> -F:	arch/arm/plat-mxc/include/mach/imxfb.h
> +F:	include/linux/platform_data/video-imxfb.h
>  F:	drivers/video/imxfb.c
>  
>  FREESCALE SOC FS_ENET DRIVER
> -- 
> 1.7.11.7
> 
> 

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

^ permalink raw reply

* Re: [RFC v2 0/5] Common Display Framework
From: Philipp Zabel @ 2012-11-26  7:53 UTC (permalink / raw)
  To: Thierry Reding
  Cc: Laurent Pinchart, linux-fbdev, dri-devel, Thomas Petazzoni,
	Tom Gall, Ragesh Radhakrishnan, Rob Clark, Kyungmin Park,
	Tomi Valkeinen, Benjamin Gaignard, Bryan Wu, Maxime Ripard,
	Vikas Sajjan, Sumit Semwal, Sebastien Guiriec, linux-media
In-Reply-To: <20121123195607.GA20990@avionic-0098.adnet.avionic-design.de>

Hi Thierry,

Am Freitag, den 23.11.2012, 20:56 +0100 schrieb Thierry Reding:
> On Thu, Nov 22, 2012 at 10:45:31PM +0100, Laurent Pinchart wrote:
> [...]
> > Display entities are accessed by driver using notifiers. Any driver can
> > register a display entity notifier with the CDF, which then calls the notifier
> > when a matching display entity is registered. The reason for this asynchronous
> > mode of operation, compared to how drivers acquire regulator or clock
> > resources, is that the display entities can use resources provided by the
> > display driver. For instance a panel can be a child of the DBI or DSI bus
> > controlled by the display device, or use a clock provided by that device. We
> > can't defer the display device probe until the panel is registered and also
> > defer the panel device probe until the display is registered. As most display
> > drivers need to handle output devices hotplug (HDMI monitors for instance),
> > handling other display entities through a notification system seemed to be the
> > easiest solution.
> > 
> > Note that this brings a different issue after registration, as display
> > controller and display entity drivers would take a reference to each other.
> > Those circular references would make driver unloading impossible. One possible
> > solution to this problem would be to simulate an unplug event for the display
> > entity, to force the display driver to release the dislay entities it uses. We
> > would need a userspace API for that though. Better solutions would of course
> > be welcome.
> 
> Maybe I don't understand all of the underlying issues correctly, but a
> parent/child model would seem like a better solution to me. We discussed
> this back when designing the DT bindings for Tegra DRM and came to the
> conclusion that the output resource of the display controller (RGB,
> HDMI, DSI or TVO) was the most suitable candidate to be the parent of
> the panel or display attached to it. The reason for that decision was
> that it keeps the flow of data or addressing of nodes consistent. So the
> chain would look something like this (on Tegra):
> 
> 	CPU
> 	+-host1x
> 	  +-dc
> 	    +-rgb
> 	    | +-panel
> 	    +-hdmi
> 	      +-monitor
> 
> In a natural way this makes the output resource the master of the panel
> or display. From a programming point of view this becomes quite easy to
> implement and is very similar to how other busses like I2C or SPI are
> modelled. In device tree these would be represented as subnodes, while
> with platform data some kind of lookup could be done like for regulators
> or alternatively a board setup registration mechanism like what's in
> place for I2C or SPI.

I second Tomi's answer. Also, describing data bus connections implicitly
with parent/child relationships doesn't work for entities with multiple
inputs. Imagine there are multiple dc's in the above diagram, and the
single hdmi encoder can be connected to either of them via multiplexing.

regards
Philipp


^ permalink raw reply

* Re: [PATCH 3/5] ARM: mach-shmobile: mackerel: Use gpio-backlight
From: Simon Horman @ 2012-11-26  1:10 UTC (permalink / raw)
  To: linux-fbdev
In-Reply-To: <1353688515-30458-4-git-send-email-laurent.pinchart+renesas@ideasonboard.com>

On Fri, Nov 23, 2012 at 05:35:13PM +0100, Laurent Pinchart wrote:
> Replace the backlight callback with a gpio-backlight platform device.
> 
> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

Acked-by: Simon Horman <horms@verge.net.au>


^ permalink raw reply

* Re: [RFC v2 0/5] Common Display Framework
From: Tomi Valkeinen @ 2012-11-24  7:15 UTC (permalink / raw)
  To: Thierry Reding
  Cc: Laurent Pinchart, linux-fbdev, dri-devel, Thomas Petazzoni,
	Philipp Zabel, Tom Gall, Ragesh Radhakrishnan, Rob Clark,
	Kyungmin Park, Benjamin Gaignard, Bryan Wu, Maxime Ripard,
	Vikas Sajjan, Sumit Semwal, Sebastien Guiriec, linux-media
In-Reply-To: <20121123195607.GA20990@avionic-0098.adnet.avionic-design.de>

[-- Attachment #1: Type: text/plain, Size: 3422 bytes --]

On 2012-11-23 21:56, Thierry Reding wrote:
> On Thu, Nov 22, 2012 at 10:45:31PM +0100, Laurent Pinchart wrote:
> [...]
>> Display entities are accessed by driver using notifiers. Any driver can
>> register a display entity notifier with the CDF, which then calls the notifier
>> when a matching display entity is registered. The reason for this asynchronous
>> mode of operation, compared to how drivers acquire regulator or clock
>> resources, is that the display entities can use resources provided by the
>> display driver. For instance a panel can be a child of the DBI or DSI bus
>> controlled by the display device, or use a clock provided by that device. We
>> can't defer the display device probe until the panel is registered and also
>> defer the panel device probe until the display is registered. As most display
>> drivers need to handle output devices hotplug (HDMI monitors for instance),
>> handling other display entities through a notification system seemed to be the
>> easiest solution.
>>
>> Note that this brings a different issue after registration, as display
>> controller and display entity drivers would take a reference to each other.
>> Those circular references would make driver unloading impossible. One possible
>> solution to this problem would be to simulate an unplug event for the display
>> entity, to force the display driver to release the dislay entities it uses. We
>> would need a userspace API for that though. Better solutions would of course
>> be welcome.
> 
> Maybe I don't understand all of the underlying issues correctly, but a
> parent/child model would seem like a better solution to me. We discussed
> this back when designing the DT bindings for Tegra DRM and came to the
> conclusion that the output resource of the display controller (RGB,
> HDMI, DSI or TVO) was the most suitable candidate to be the parent of
> the panel or display attached to it. The reason for that decision was
> that it keeps the flow of data or addressing of nodes consistent. So the
> chain would look something like this (on Tegra):
> 
> 	CPU
> 	+-host1x
> 	  +-dc
> 	    +-rgb
> 	    | +-panel
> 	    +-hdmi
> 	      +-monitor
> 
> In a natural way this makes the output resource the master of the panel
> or display. From a programming point of view this becomes quite easy to
> implement and is very similar to how other busses like I2C or SPI are
> modelled. In device tree these would be represented as subnodes, while
> with platform data some kind of lookup could be done like for regulators
> or alternatively a board setup registration mechanism like what's in
> place for I2C or SPI.

You didn't explicitly say it, but I presume you are talking about the
device model for panels, not just how to refer to the outputs.

How would you deal with a, say, DPI panel that is controlled via I2C or
SPI? You can have the panel device be both a panel device, child of a
RGB output, and an i2c device.

The model you propose is currently used in omapdss, and while it seems
simple and logical, it's not that simple with panels/chips with separate
control and data busses.

I think it makes more sense to consider the device as a child of the
control bus. So a DPI panel controlled via I2C is an I2C device, and it
just happens to use a DPI video output as a resource (like it could use
a regulator, gpio, etc).

 Tomi



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 899 bytes --]

^ permalink raw reply

* [PATCH 11/24] MAINTAINERS: fix .../plat-mxc/include/mach/imxfb.h
From: Cesar Eduardo Barros @ 2012-11-24  0:26 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1353716808-16375-1-git-send-email-cesarb@cesarb.net>

This file was moved to include/linux/platform_data/video-imxfb.h by
commit 82906b1 (ARM: imx: move platform_data definitions).

Cc: Sascha Hauer <kernel@pengutronix.de>
Cc: linux-fbdev@vger.kernel.org
Cc: linux-arm-kernel@lists.infradead.org
Signed-off-by: Cesar Eduardo Barros <cesarb@cesarb.net>
---
 MAINTAINERS | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/MAINTAINERS b/MAINTAINERS
index a67a67a..887d717 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3137,7 +3137,7 @@ M:	Sascha Hauer <kernel@pengutronix.de>
 L:	linux-fbdev@vger.kernel.org
 L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:	Maintained
-F:	arch/arm/plat-mxc/include/mach/imxfb.h
+F:	include/linux/platform_data/video-imxfb.h
 F:	drivers/video/imxfb.c
 
 FREESCALE SOC FS_ENET DRIVER
-- 
1.7.11.7


^ permalink raw reply related

* Re: [RFC v2 0/5] Common Display Framework
From: Sascha Hauer @ 2012-11-23 21:41 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: linux-fbdev, dri-devel, linux-media, Archit Taneja,
	Benjamin Gaignard, Bryan Wu, Inki Dae, Jesse Barker,
	Kyungmin Park, Marcus Lorentzon, Maxime Ripard, Philipp Zabel,
	Ragesh Radhakrishnan, Rob Clark, Sebastien Guiriec, Sumit Semwal,
	Thomas Petazzoni, Tom Gall, Tomi Valkeinen, Vikas Sajjan
In-Reply-To: <1353620736-6517-1-git-send-email-laurent.pinchart@ideasonboard.com>

Hi Laurent,

On Thu, Nov 22, 2012 at 10:45:31PM +0100, Laurent Pinchart wrote:
> From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
> 
 
> The CDF models this using a Russian doll's model. From the display controller
> point of view only the first external entity (LVDS to DSI converter) is
> visible. The display controller thus calls the control operations implemented
> by the LVDS to DSI transmitter driver (left-most green arrow). The driver is
> aware of the next entity in the chain,

I can't find this in the code. I can see the video operations
propagating upstream using the source field of struct display_entity,
but how do the control operations propagate downstream? Am I missing
something?

Sascha


-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

^ permalink raw reply

* Re: [RFC v2 0/5] Common Display Framework
From: Thierry Reding @ 2012-11-23 19:56 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: linux-fbdev, dri-devel, Thomas Petazzoni, Philipp Zabel, Tom Gall,
	Ragesh Radhakrishnan, Rob Clark, Kyungmin Park, Tomi Valkeinen,
	Benjamin Gaignard, Bryan Wu, Maxime Ripard, Vikas Sajjan,
	Sumit Semwal, Sebastien Guiriec, linux-media
In-Reply-To: <1353620736-6517-1-git-send-email-laurent.pinchart@ideasonboard.com>

[-- Attachment #1: Type: text/plain, Size: 2570 bytes --]

On Thu, Nov 22, 2012 at 10:45:31PM +0100, Laurent Pinchart wrote:
[...]
> Display entities are accessed by driver using notifiers. Any driver can
> register a display entity notifier with the CDF, which then calls the notifier
> when a matching display entity is registered. The reason for this asynchronous
> mode of operation, compared to how drivers acquire regulator or clock
> resources, is that the display entities can use resources provided by the
> display driver. For instance a panel can be a child of the DBI or DSI bus
> controlled by the display device, or use a clock provided by that device. We
> can't defer the display device probe until the panel is registered and also
> defer the panel device probe until the display is registered. As most display
> drivers need to handle output devices hotplug (HDMI monitors for instance),
> handling other display entities through a notification system seemed to be the
> easiest solution.
> 
> Note that this brings a different issue after registration, as display
> controller and display entity drivers would take a reference to each other.
> Those circular references would make driver unloading impossible. One possible
> solution to this problem would be to simulate an unplug event for the display
> entity, to force the display driver to release the dislay entities it uses. We
> would need a userspace API for that though. Better solutions would of course
> be welcome.

Maybe I don't understand all of the underlying issues correctly, but a
parent/child model would seem like a better solution to me. We discussed
this back when designing the DT bindings for Tegra DRM and came to the
conclusion that the output resource of the display controller (RGB,
HDMI, DSI or TVO) was the most suitable candidate to be the parent of
the panel or display attached to it. The reason for that decision was
that it keeps the flow of data or addressing of nodes consistent. So the
chain would look something like this (on Tegra):

	CPU
	+-host1x
	  +-dc
	    +-rgb
	    | +-panel
	    +-hdmi
	      +-monitor

In a natural way this makes the output resource the master of the panel
or display. From a programming point of view this becomes quite easy to
implement and is very similar to how other busses like I2C or SPI are
modelled. In device tree these would be represented as subnodes, while
with platform data some kind of lookup could be done like for regulators
or alternatively a board setup registration mechanism like what's in
place for I2C or SPI.

Thierry

[-- Attachment #2: Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply

* [PATCH 5/5] sh: kfr2r09: Use lv5207lp backlight
From: Laurent Pinchart @ 2012-11-23 16:35 UTC (permalink / raw)
  To: linux-fbdev

Replace the backlight callback with a lv5207lp backlight platform
device.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 arch/sh/boards/mach-kfr2r09/lcd_wqvga.c     |   48 ---------------------------
 arch/sh/boards/mach-kfr2r09/setup.c         |   19 ++++++++---
 arch/sh/include/mach-kfr2r09/mach/kfr2r09.h |    2 -
 3 files changed, 14 insertions(+), 55 deletions(-)

diff --git a/arch/sh/boards/mach-kfr2r09/lcd_wqvga.c b/arch/sh/boards/mach-kfr2r09/lcd_wqvga.c
index c620503..355a78a 100644
--- a/arch/sh/boards/mach-kfr2r09/lcd_wqvga.c
+++ b/arch/sh/boards/mach-kfr2r09/lcd_wqvga.c
@@ -276,51 +276,3 @@ void kfr2r09_lcd_start(void *sohandle, struct sh_mobile_lcdc_sys_bus_ops *so)
 {
 	write_memory_start(sohandle, so);
 }
-
-#define CTRL_CKSW       0x10
-#define CTRL_C10        0x20
-#define CTRL_CPSW       0x80
-#define MAIN_MLED4      0x40
-#define MAIN_MSW        0x80
-
-int kfr2r09_lcd_set_brightness(int brightness)
-{
-	struct i2c_adapter *a;
-	struct i2c_msg msg;
-	unsigned char buf[2];
-	int ret;
-
-	a = i2c_get_adapter(0);
-	if (!a)
-		return -ENODEV;
-
-	buf[0] = 0x00;
-	if (brightness)
-		buf[1] = CTRL_CPSW | CTRL_C10 | CTRL_CKSW;
-	else
-		buf[1] = 0;
-
-	msg.addr = 0x75;
-	msg.buf = buf;
-	msg.len = 2;
-	msg.flags = 0;
-	ret = i2c_transfer(a, &msg, 1);
-	if (ret != 1)
-		return -ENODEV;
-
-	buf[0] = 0x01;
-	if (brightness)
-		buf[1] = MAIN_MSW | MAIN_MLED4 | 0x0c;
-	else
-		buf[1] = 0;
-
-	msg.addr = 0x75;
-	msg.buf = buf;
-	msg.len = 2;
-	msg.flags = 0;
-	ret = i2c_transfer(a, &msg, 1);
-	if (ret != 1)
-		return -ENODEV;
-
-	return 0;
-}
diff --git a/arch/sh/boards/mach-kfr2r09/setup.c b/arch/sh/boards/mach-kfr2r09/setup.c
index ab502f12..1df4398 100644
--- a/arch/sh/boards/mach-kfr2r09/setup.c
+++ b/arch/sh/boards/mach-kfr2r09/setup.c
@@ -21,6 +21,7 @@
 #include <linux/input.h>
 #include <linux/input/sh_keysc.h>
 #include <linux/i2c.h>
+#include <linux/platform_data/lv5207lp.h>
 #include <linux/regulator/fixed.h>
 #include <linux/regulator/machine.h>
 #include <linux/usb/r8a66597.h>
@@ -159,11 +160,6 @@ static struct sh_mobile_lcdc_info kfr2r09_sh_lcdc_info = {
 			.setup_sys = kfr2r09_lcd_setup,
 			.start_transfer = kfr2r09_lcd_start,
 		},
-		.bl_info = {
-			.name = "sh_mobile_lcdc_bl",
-			.max_brightness = 1,
-			.set_brightness = kfr2r09_lcd_set_brightness,
-		},
 		.sys_bus_cfg = {
 			.ldmt2r = 0x07010904,
 			.ldmt3r = 0x14012914,
@@ -195,6 +191,17 @@ static struct platform_device kfr2r09_sh_lcdc_device = {
 	},
 };
 
+static struct lv5207lp_platform_data kfr2r09_backlight_data = {
+	.fbdev = &kfr2r09_sh_lcdc_device.dev,
+	.def_value = 13,
+	.max_value = 13,
+};
+
+static struct i2c_board_info kfr2r09_backlight_board_info = {
+	I2C_BOARD_INFO("lv5207lp", 0x75),
+	.platform_data = &kfr2r09_backlight_data,
+};
+
 static struct r8a66597_platdata kfr2r09_usb0_gadget_data = {
 	.on_chip = 1,
 };
@@ -627,6 +634,8 @@ static int __init kfr2r09_devices_setup(void)
 	gpio_request(GPIO_FN_SDHI0CMD, NULL);
 	gpio_request(GPIO_FN_SDHI0CLK, NULL);
 
+	i2c_register_board_info(0, &kfr2r09_backlight_board_info, 1);
+
 	return platform_add_devices(kfr2r09_devices,
 				    ARRAY_SIZE(kfr2r09_devices));
 }
diff --git a/arch/sh/include/mach-kfr2r09/mach/kfr2r09.h b/arch/sh/include/mach-kfr2r09/mach/kfr2r09.h
index c20c9e5..79f154e 100644
--- a/arch/sh/include/mach-kfr2r09/mach/kfr2r09.h
+++ b/arch/sh/include/mach-kfr2r09/mach/kfr2r09.h
@@ -4,13 +4,11 @@
 #include <video/sh_mobile_lcdc.h>
 
 #if defined(CONFIG_FB_SH_MOBILE_LCDC) || defined(CONFIG_FB_SH_MOBILE_LCDC_MODULE)
-int kfr2r09_lcd_set_brightness(int brightness);
 int kfr2r09_lcd_setup(void *sys_ops_handle,
 		      struct sh_mobile_lcdc_sys_bus_ops *sys_ops);
 void kfr2r09_lcd_start(void *sys_ops_handle,
 		       struct sh_mobile_lcdc_sys_bus_ops *sys_ops);
 #else
-static int kfr2r09_lcd_set_brightness(int brightness) {}
 static int kfr2r09_lcd_setup(void *sys_ops_handle,
 				struct sh_mobile_lcdc_sys_bus_ops *sys_ops)
 {
-- 
1.7.8.6


^ permalink raw reply related

* [PATCH 4/5] sh: ecovec24: Use gpio-backlight
From: Laurent Pinchart @ 2012-11-23 16:35 UTC (permalink / raw)
  To: linux-fbdev

Replace the backlight callback with a gpio-backlight platform device.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 arch/sh/boards/mach-ecovec24/setup.c |   37 ++++++++++++++++++---------------
 1 files changed, 20 insertions(+), 17 deletions(-)

diff --git a/arch/sh/boards/mach-ecovec24/setup.c b/arch/sh/boards/mach-ecovec24/setup.c
index 3fede45..865f765 100644
--- a/arch/sh/boards/mach-ecovec24/setup.c
+++ b/arch/sh/boards/mach-ecovec24/setup.c
@@ -33,6 +33,7 @@
 #include <linux/sh_eth.h>
 #include <linux/sh_intc.h>
 #include <linux/videodev2.h>
+#include <video/gpio_backlight.h>
 #include <video/sh_mobile_lcdc.h>
 #include <sound/sh_fsi.h>
 #include <sound/simple_card.h>
@@ -291,7 +292,7 @@ static struct platform_device usbhs_device = {
 	.resource	= usbhs_resources,
 };
 
-/* LCDC */
+/* LCDC and backlight */
 static const struct fb_videomode ecovec_lcd_modes[] = {
 	{
 		.name		= "Panel",
@@ -322,13 +323,6 @@ static const struct fb_videomode ecovec_dvi_modes[] = {
 	},
 };
 
-static int ecovec24_set_brightness(int brightness)
-{
-	gpio_set_value(GPIO_PTR1, brightness);
-
-	return 0;
-}
-
 static struct sh_mobile_lcdc_info lcdc_info = {
 	.ch[0] = {
 		.interface_type = RGB18,
@@ -338,11 +332,6 @@ static struct sh_mobile_lcdc_info lcdc_info = {
 			.width = 152,
 			.height = 91,
 		},
-		.bl_info = {
-			.name = "sh_mobile_lcdc_bl",
-			.max_brightness = 1,
-			.set_brightness = ecovec24_set_brightness,
-		},
 	}
 };
 
@@ -368,6 +357,20 @@ static struct platform_device lcdc_device = {
 	},
 };
 
+static struct gpio_backlight_platform_data gpio_backlight_data = {
+	.fbdev = &lcdc_device.dev,
+	.gpio = GPIO_PTR1,
+	.def_value = 1,
+	.name = "backlight",
+};
+
+static struct platform_device gpio_backlight_device = {
+	.name = "gpio-backlight",
+	.dev = {
+		.platform_data = &gpio_backlight_data,
+	},
+};
+
 /* CEU0 */
 static struct sh_mobile_ceu_info sh_mobile_ceu0_info = {
 	.flags = SH_CEU_FLAG_USE_8BIT_BUS,
@@ -1046,6 +1049,7 @@ static struct platform_device *ecovec_devices[] __initdata = {
 	&usb1_common_device,
 	&usbhs_device,
 	&lcdc_device,
+	&gpio_backlight_device,
 	&ceu0_device,
 	&ceu1_device,
 	&keysc_device,
@@ -1236,11 +1240,9 @@ static int __init arch_setup(void)
 
 	gpio_request(GPIO_PTE6, NULL);
 	gpio_request(GPIO_PTU1, NULL);
-	gpio_request(GPIO_PTR1, NULL);
 	gpio_request(GPIO_PTA2, NULL);
 	gpio_direction_input(GPIO_PTE6);
 	gpio_direction_output(GPIO_PTU1, 0);
-	gpio_direction_output(GPIO_PTR1, 0);
 	gpio_direction_output(GPIO_PTA2, 0);
 
 	/* I/O buffer drive ability is high */
@@ -1253,6 +1255,9 @@ static int __init arch_setup(void)
 		lcdc_info.ch[0].lcd_modes		= ecovec_dvi_modes;
 		lcdc_info.ch[0].num_modes		= ARRAY_SIZE(ecovec_dvi_modes);
 
+		/* No backlight */
+		gpio_backlight_data.fbdev = NULL;
+
 		gpio_set_value(GPIO_PTA2, 1);
 		gpio_set_value(GPIO_PTU1, 1);
 	} else {
@@ -1262,8 +1267,6 @@ static int __init arch_setup(void)
 		lcdc_info.ch[0].lcd_modes		= ecovec_lcd_modes;
 		lcdc_info.ch[0].num_modes		= ARRAY_SIZE(ecovec_lcd_modes);
 
-		gpio_set_value(GPIO_PTR1, 1);
-
 		/* FIXME
 		 *
 		 * LCDDON control is needed for Panel,
-- 
1.7.8.6


^ permalink raw reply related

* [PATCH 3/5] ARM: mach-shmobile: mackerel: Use gpio-backlight
From: Laurent Pinchart @ 2012-11-23 16:35 UTC (permalink / raw)
  To: linux-fbdev

Replace the backlight callback with a gpio-backlight platform device.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 arch/arm/mach-shmobile/board-mackerel.c |   34 +++++++++++++++---------------
 1 files changed, 17 insertions(+), 17 deletions(-)

diff --git a/arch/arm/mach-shmobile/board-mackerel.c b/arch/arm/mach-shmobile/board-mackerel.c
index bfd2dc8..ea35727 100644
--- a/arch/arm/mach-shmobile/board-mackerel.c
+++ b/arch/arm/mach-shmobile/board-mackerel.c
@@ -48,7 +48,7 @@
 #include <linux/tca6416_keypad.h>
 #include <linux/usb/renesas_usbhs.h>
 #include <linux/dma-mapping.h>
-
+#include <video/gpio_backlight.h>
 #include <video/sh_mobile_hdmi.h>
 #include <video/sh_mobile_lcdc.h>
 #include <media/sh_mobile_ceu.h>
@@ -347,7 +347,7 @@ static struct platform_device meram_device = {
 	},
 };
 
-/* LCDC */
+/* LCDC and backlight */
 static struct fb_videomode mackerel_lcdc_modes[] = {
 	{
 		.name		= "WVGA Panel",
@@ -363,13 +363,6 @@ static struct fb_videomode mackerel_lcdc_modes[] = {
 	},
 };
 
-static int mackerel_set_brightness(int brightness)
-{
-	gpio_set_value(GPIO_PORT31, brightness);
-
-	return 0;
-}
-
 static const struct sh_mobile_meram_cfg lcd_meram_cfg = {
 	.icb[0] = {
 		.meram_size     = 0x40,
@@ -394,11 +387,6 @@ static struct sh_mobile_lcdc_info lcdc_info = {
 			.width		= 152,
 			.height		= 91,
 		},
-		.bl_info = {
-			.name = "sh_mobile_lcdc_bl",
-			.max_brightness = 1,
-			.set_brightness = mackerel_set_brightness,
-		},
 		.meram_cfg = &lcd_meram_cfg,
 	}
 };
@@ -426,6 +414,20 @@ static struct platform_device lcdc_device = {
 	},
 };
 
+static struct gpio_backlight_platform_data gpio_backlight_data = {
+	.fbdev = &lcdc_device.dev,
+	.gpio = GPIO_PORT31,
+	.def_value = 1,
+	.name = "backlight",
+};
+
+static struct platform_device gpio_backlight_device = {
+	.name = "gpio-backlight",
+	.dev = {
+		.platform_data = &gpio_backlight_data,
+	},
+};
+
 /* HDMI */
 static struct sh_mobile_hdmi_info hdmi_info = {
 	.flags		= HDMI_SND_SRC_SPDIF,
@@ -1322,6 +1324,7 @@ static struct platform_device *mackerel_devices[] __initdata = {
 	&nor_flash_device,
 	&smc911x_device,
 	&lcdc_device,
+	&gpio_backlight_device,
 	&usbhs0_device,
 	&usbhs1_device,
 	&leds_device,
@@ -1472,9 +1475,6 @@ static void __init mackerel_init(void)
 	gpio_request(GPIO_FN_LCDDISP,  NULL);
 	gpio_request(GPIO_FN_LCDDCK,   NULL);
 
-	gpio_request(GPIO_PORT31, NULL); /* backlight */
-	gpio_direction_output(GPIO_PORT31, 0); /* off by default */
-
 	gpio_request(GPIO_PORT151, NULL); /* LCDDON */
 	gpio_direction_output(GPIO_PORT151, 1);
 
-- 
1.7.8.6


^ permalink raw reply related

* [PATCH 2/5] backlight: Add Sanyo LV5207LP backlight driver
From: Laurent Pinchart @ 2012-11-23 16:35 UTC (permalink / raw)
  To: linux-fbdev

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/video/backlight/Kconfig        |    6 +
 drivers/video/backlight/Makefile       |    1 +
 drivers/video/backlight/lv5207lp.c     |  171 ++++++++++++++++++++++++++++++++
 include/linux/platform_data/lv5207lp.h |   20 ++++
 4 files changed, 198 insertions(+), 0 deletions(-)
 create mode 100644 drivers/video/backlight/lv5207lp.c
 create mode 100644 include/linux/platform_data/lv5207lp.h

diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig
index 259442d..92ce5aa 100644
--- a/drivers/video/backlight/Kconfig
+++ b/drivers/video/backlight/Kconfig
@@ -397,6 +397,12 @@ config BACKLIGHT_GPIO
 	  If you have a LCD backlight adjustable by GPIO, say Y to enable
 	  this driver.
 
+config BACKLIGHT_LV5207LP
+	tristate "Sanyo LV5207LP Backlight"
+	depends on I2C
+	help
+	  If you have a Sanyo LV5207LP say Y to enable the backlight driver.
+
 endif # BACKLIGHT_CLASS_DEVICE
 
 endif # BACKLIGHT_LCD_SUPPORT
diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile
index ec91c4a..125b8ad 100644
--- a/drivers/video/backlight/Makefile
+++ b/drivers/video/backlight/Makefile
@@ -46,3 +46,4 @@ obj-$(CONFIG_BACKLIGHT_AAT2870) += aat2870_bl.o
 obj-$(CONFIG_BACKLIGHT_OT200) += ot200_bl.o
 obj-$(CONFIG_BACKLIGHT_TPS65217) += tps65217_bl.o
 obj-$(CONFIG_BACKLIGHT_GPIO)	+= gpio_backlight.o
+obj-$(CONFIG_BACKLIGHT_LV5207LP)	+= lv5207lp.o
diff --git a/drivers/video/backlight/lv5207lp.c b/drivers/video/backlight/lv5207lp.c
new file mode 100644
index 0000000..b06f35c
--- /dev/null
+++ b/drivers/video/backlight/lv5207lp.c
@@ -0,0 +1,171 @@
+/*
+ * Sanyo LV5207LP LED Driver
+ *
+ * Copyright (C) 2012 Ideas on board SPRL
+ *
+ * Contact: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/backlight.h>
+#include <linux/err.h>
+#include <linux/fb.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/platform_data/lv5207lp.h>
+
+#define LV5207LP_CTRL1			0x00
+#define LV5207LP_CPSW			(1 << 7)
+#define LV5207LP_SCTEN			(1 << 6)
+#define LV5207LP_C10			(1 << 5)
+#define LV5207LP_CKSW			(1 << 4)
+#define LV5207LP_RSW			(1 << 3)
+#define LV5207LP_GSW			(1 << 2)
+#define LV5207LP_BSW			(1 << 1)
+#define LV5207LP_CTRL2			0x01
+#define LV5207LP_MSW			(1 << 7)
+#define LV5207LP_MLED4			(1 << 6)
+#define LV5207LP_RED			0x02
+#define LV5207LP_GREEN			0x03
+#define LV5207LP_BLUE			0x04
+
+#define LV5207LP_MAX_BRIGHTNESS		32
+
+struct lv5207lp {
+	struct i2c_client *client;
+	struct backlight_device *backlight;
+	struct lv5207lp_platform_data *pdata;
+};
+
+static int lv5207lp_write(struct lv5207lp *lv, u8 reg, u8 data)
+{
+	return i2c_smbus_write_byte_data(lv->client, reg, data);
+}
+
+static int lv5207lp_backlight_update_status(struct backlight_device *backlight)
+{
+	struct lv5207lp *lv = bl_get_data(backlight);
+	int brightness = backlight->props.brightness;
+
+	if (backlight->props.power != FB_BLANK_UNBLANK ||
+	    backlight->props.fb_blank != FB_BLANK_UNBLANK ||
+	    backlight->props.state & (BL_CORE_SUSPENDED | BL_CORE_FBBLANK))
+		brightness = 0;
+
+	if (brightness) {
+		lv5207lp_write(lv, LV5207LP_CTRL1,
+			       LV5207LP_CPSW | LV5207LP_C10 | LV5207LP_CKSW);
+		lv5207lp_write(lv, LV5207LP_CTRL2,
+			       LV5207LP_MSW | LV5207LP_MLED4 |
+			       (brightness - 1));
+	} else {
+		lv5207lp_write(lv, LV5207LP_CTRL1, 0);
+		lv5207lp_write(lv, LV5207LP_CTRL2, 0);
+	}
+
+	return 0;
+}
+
+static int lv5207lp_backlight_get_brightness(struct backlight_device *backlight)
+{
+	return backlight->props.brightness;
+}
+
+static int lv5207lp_backlight_check_fb(struct backlight_device *backlight,
+				       struct fb_info *info)
+{
+	struct lv5207lp *lv = bl_get_data(backlight);
+
+	return lv->pdata->fbdev = info->dev;
+}
+
+static const struct backlight_ops lv5207lp_backlight_ops = {
+	.options	= BL_CORE_SUSPENDRESUME,
+	.update_status	= lv5207lp_backlight_update_status,
+	.get_brightness	= lv5207lp_backlight_get_brightness,
+	.check_fb	= lv5207lp_backlight_check_fb,
+};
+
+static int lv5207lp_probe(struct i2c_client *client,
+			  const struct i2c_device_id *id)
+{
+	struct lv5207lp_platform_data *pdata = client->dev.platform_data;
+	struct backlight_device *backlight;
+	struct backlight_properties props;
+	struct lv5207lp *lv;
+
+	if (pdata = NULL) {
+		dev_err(&client->dev, "No platform data supplied\n");
+		return -EINVAL;
+	}
+
+	if (!i2c_check_functionality(client->adapter,
+				     I2C_FUNC_SMBUS_BYTE_DATA)) {
+		dev_warn(&client->dev,
+			 "I2C adapter doesn't support I2C_FUNC_SMBUS_BYTE\n");
+		return -EIO;
+	}
+
+	lv = devm_kzalloc(&client->dev, sizeof(*lv), GFP_KERNEL);
+	if (!lv)
+		return -ENOMEM;
+
+	lv->client = client;
+	lv->pdata = pdata;
+
+	memset(&props, 0, sizeof(props));
+	props.type = BACKLIGHT_RAW;
+	props.max_brightness = min_t(unsigned int, pdata->max_value,
+				     LV5207LP_MAX_BRIGHTNESS);
+	props.brightness = clamp_t(unsigned int, pdata->def_value, 0,
+				   props.max_brightness);
+
+	backlight = backlight_device_register(dev_name(&client->dev),
+					      &lv->client->dev, lv,
+					      &lv5207lp_backlight_ops, &props);
+	if (IS_ERR(backlight)) {
+		dev_err(&client->dev, "failed to register backlight\n");
+		return PTR_ERR(backlight);
+	}
+
+	backlight_update_status(backlight);
+	i2c_set_clientdata(client, backlight);
+
+	return 0;
+}
+
+static int lv5207lp_remove(struct i2c_client *client)
+{
+	struct backlight_device *backlight = i2c_get_clientdata(client);
+
+	backlight->props.brightness = 0;
+	backlight_update_status(backlight);
+	backlight_device_unregister(backlight);
+
+	return 0;
+}
+
+static const struct i2c_device_id lv5207lp_ids[] = {
+	{ "lv5207lp", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, lv5207lp_ids);
+
+static struct i2c_driver lv5207lp_driver = {
+	.driver = {
+		.name = "lv5207lp",
+	},
+	.probe = lv5207lp_probe,
+	.remove = lv5207lp_remove,
+	.id_table = lv5207lp_ids,
+};
+
+module_i2c_driver(lv5207lp_driver);
+
+MODULE_DESCRIPTION("Sanyo LV5207LP Backlight Driver");
+MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/platform_data/lv5207lp.h b/include/linux/platform_data/lv5207lp.h
new file mode 100644
index 0000000..ac95cb1
--- /dev/null
+++ b/include/linux/platform_data/lv5207lp.h
@@ -0,0 +1,20 @@
+/*
+ * lv5207lp.h - Sanyo LV5207LP LEDs Driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef __LV5207LP_H__
+#define __LV5207LP_H__
+
+struct device;
+
+struct lv5207lp_platform_data {
+	struct device *fbdev;
+	unsigned int max_value;
+	unsigned int def_value;
+};
+
+#endif
+
-- 
1.7.8.6


^ permalink raw reply related

* [PATCH 1/5] backlight: Add GPIO-based backlight driver
From: Laurent Pinchart @ 2012-11-23 16:35 UTC (permalink / raw)
  To: linux-fbdev

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 drivers/video/backlight/Kconfig          |    7 ++
 drivers/video/backlight/Makefile         |    1 +
 drivers/video/backlight/gpio_backlight.c |  158 ++++++++++++++++++++++++++++++
 include/video/gpio_backlight.h           |   21 ++++
 4 files changed, 187 insertions(+), 0 deletions(-)
 create mode 100644 drivers/video/backlight/gpio_backlight.c
 create mode 100644 include/video/gpio_backlight.h

diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig
index 765a945..259442d 100644
--- a/drivers/video/backlight/Kconfig
+++ b/drivers/video/backlight/Kconfig
@@ -390,6 +390,13 @@ config BACKLIGHT_TPS65217
 	  If you have a Texas Instruments TPS65217 say Y to enable the
 	  backlight driver.
 
+config BACKLIGHT_GPIO
+	tristate "Generic GPIO based Backlight Driver"
+	depends on GENERIC_GPIO
+	help
+	  If you have a LCD backlight adjustable by GPIO, say Y to enable
+	  this driver.
+
 endif # BACKLIGHT_CLASS_DEVICE
 
 endif # BACKLIGHT_LCD_SUPPORT
diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile
index e7ce729..ec91c4a 100644
--- a/drivers/video/backlight/Makefile
+++ b/drivers/video/backlight/Makefile
@@ -45,3 +45,4 @@ obj-$(CONFIG_BACKLIGHT_PCF50633)	+= pcf50633-backlight.o
 obj-$(CONFIG_BACKLIGHT_AAT2870) += aat2870_bl.o
 obj-$(CONFIG_BACKLIGHT_OT200) += ot200_bl.o
 obj-$(CONFIG_BACKLIGHT_TPS65217) += tps65217_bl.o
+obj-$(CONFIG_BACKLIGHT_GPIO)	+= gpio_backlight.o
diff --git a/drivers/video/backlight/gpio_backlight.c b/drivers/video/backlight/gpio_backlight.c
new file mode 100644
index 0000000..5a8cd34
--- /dev/null
+++ b/drivers/video/backlight/gpio_backlight.c
@@ -0,0 +1,158 @@
+/*
+ * gpio_backlight.c - Simple GPIO-controlled backlight
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/backlight.h>
+#include <linux/err.h>
+#include <linux/fb.h>
+#include <linux/gpio.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <video/gpio_backlight.h>
+
+struct gpio_backlight {
+	struct device *dev;
+	struct device *fbdev;
+
+	int gpio;
+	int active;
+};
+
+static int gpio_backlight_update_status(struct backlight_device *bl)
+{
+	struct gpio_backlight *gbl = bl_get_data(bl);
+	int brightness = bl->props.brightness;
+
+	if (bl->props.power != FB_BLANK_UNBLANK ||
+	    bl->props.fb_blank != FB_BLANK_UNBLANK ||
+	    bl->props.state & (BL_CORE_SUSPENDED | BL_CORE_FBBLANK))
+		brightness = 0;
+
+	gpio_set_value(gbl->gpio, brightness ? gbl->active : !gbl->active);
+
+	return 0;
+}
+
+static int gpio_backlight_get_brightness(struct backlight_device *bl)
+{
+	return bl->props.brightness;
+}
+
+static int gpio_backlight_check_fb(struct backlight_device *bl,
+				   struct fb_info *info)
+{
+	struct gpio_backlight *gbl = bl_get_data(bl);
+
+	return gbl->fbdev = info->dev;
+}
+
+static const struct backlight_ops gpio_backlight_ops = {
+	.update_status	= gpio_backlight_update_status,
+	.get_brightness	= gpio_backlight_get_brightness,
+	.check_fb	= gpio_backlight_check_fb,
+};
+
+#ifdef CONFIG_PM
+static int gpio_backlight_suspend(struct device *dev)
+{
+	struct backlight_device *bl = dev_get_drvdata(dev);
+	struct gpio_backlight *gbl = bl_get_data(bl);
+
+	gpio_set_value(gbl->gpio, !gbl->active);
+
+	return 0;
+}
+
+static int gpio_backlight_resume(struct device *dev)
+{
+	struct backlight_device *bl = dev_get_drvdata(dev);
+
+	backlight_update_status(bl);
+	return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(gpio_backlight_pm_ops, gpio_backlight_suspend,
+			 gpio_backlight_resume);
+
+#endif
+
+static int __devinit gpio_backlight_probe(struct platform_device *pdev)
+{
+	struct gpio_backlight_platform_data *pdata = pdev->dev.platform_data;
+	struct backlight_properties props;
+	struct backlight_device *bl;
+	struct gpio_backlight *gbl;
+	int ret;
+
+	gbl = devm_kzalloc(&pdev->dev, sizeof(*gbl), GFP_KERNEL);
+	if (gbl = NULL)
+		return -ENOMEM;
+
+	gbl->dev = &pdev->dev;
+
+	if (!pdata) {
+		dev_err(&pdev->dev, "failed to find platform data\n");
+		return -ENODEV;
+	}
+
+	gbl->fbdev = pdata->fbdev;
+	gbl->gpio = pdata->gpio;
+	gbl->active = pdata->active_low ? 0 : 1;
+
+	ret = devm_gpio_request_one(gbl->dev, gbl->gpio, GPIOF_DIR_OUT,
+				    pdata->name);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "unable to request GPIO\n");
+		return ret;
+	}
+
+	memset(&props, 0, sizeof(props));
+	props.type = BACKLIGHT_RAW;
+	props.max_brightness = 1;
+	bl = backlight_device_register(dev_name(&pdev->dev), &pdev->dev, gbl,
+				       &gpio_backlight_ops, &props);
+	if (IS_ERR(bl)) {
+		dev_err(&pdev->dev, "failed to register backlight\n");
+		return PTR_ERR(bl);
+	}
+
+	bl->props.brightness = pdata->def_value;
+	backlight_update_status(bl);
+
+	platform_set_drvdata(pdev, bl);
+	return 0;
+}
+
+static int __devexit gpio_backlight_remove(struct platform_device *pdev)
+{
+	struct backlight_device *bl = platform_get_drvdata(pdev);
+
+	backlight_device_unregister(bl);
+	return 0;
+}
+
+static struct platform_driver gpio_backlight_driver = {
+	.driver		= {
+		.name		= "gpio-backlight",
+		.owner		= THIS_MODULE,
+#ifdef CONFIG_PM
+		.pm		= &gpio_backlight_pm_ops,
+#endif
+	},
+	.probe		= gpio_backlight_probe,
+	.remove		= __devexit_p(gpio_backlight_remove),
+};
+
+module_platform_driver(gpio_backlight_driver);
+
+MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>");
+MODULE_DESCRIPTION("GPIO-based Backlight Driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:gpio-backlight");
diff --git a/include/video/gpio_backlight.h b/include/video/gpio_backlight.h
new file mode 100644
index 0000000..5ae0d9c
--- /dev/null
+++ b/include/video/gpio_backlight.h
@@ -0,0 +1,21 @@
+/*
+ * gpio_backlight.h - Simple GPIO-controlled backlight
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef __GPIO_BACKLIGHT_H__
+#define __GPIO_BACKLIGHT_H__
+
+struct device;
+
+struct gpio_backlight_platform_data {
+	struct device *fbdev;
+	int gpio;
+	int def_value;
+	bool active_low;
+	const char *name;
+};
+
+#endif
-- 
1.7.8.6


^ permalink raw reply related

* [PATCH 0/5] Backlight drivers for SH and ARM SH-Mobile boards
From: Laurent Pinchart @ 2012-11-23 16:35 UTC (permalink / raw)
  To: linux-fbdev

Hello,

Here are two backlight drivers used by SH and ARM SH-Mobile boards.

The first driver supports simple GPIO-controlled backlights that are turned on
or off by a single GPIO (either active high or active low).

The second driver supports the Sanyo LV5207LP LED driver
(http://www.onsemi.com/pub_link/Collateral/ENA0943-D.PDF) and exposes the main
LED only as a backlight device, as that's all the board I need to driver for
uses.

The last three patches port the ARM SH-Mobile Mackerel, SH Ecovec24 and SH
KFR2R09 boards to use the new backlight drivers. The code has been compile
tested on all three platforms and runtime tested on Mackerel only as I don't
have access to the SH boards.

Laurent Pinchart (5):
  backlight: Add GPIO-based backlight driver
  backlight: Add Sanyo LV5207LP backlight driver
  ARM: mach-shmobile: mackerel: Use gpio-backlight
  sh: ecovec24: Use gpio-backlight
  sh: kfr2r09: Use lv5207lp backlight

 arch/arm/mach-shmobile/board-mackerel.c     |   34 +++---
 arch/sh/boards/mach-ecovec24/setup.c        |   37 +++---
 arch/sh/boards/mach-kfr2r09/lcd_wqvga.c     |   48 --------
 arch/sh/boards/mach-kfr2r09/setup.c         |   19 ++-
 arch/sh/include/mach-kfr2r09/mach/kfr2r09.h |    2 -
 drivers/video/backlight/Kconfig             |   13 ++
 drivers/video/backlight/Makefile            |    2 +
 drivers/video/backlight/gpio_backlight.c    |  158 +++++++++++++++++++++++++
 drivers/video/backlight/lv5207lp.c          |  171 +++++++++++++++++++++++++++
 include/linux/platform_data/lv5207lp.h      |   20 +++
 include/video/gpio_backlight.h              |   21 ++++
 11 files changed, 436 insertions(+), 89 deletions(-)
 create mode 100644 drivers/video/backlight/gpio_backlight.c
 create mode 100644 drivers/video/backlight/lv5207lp.c
 create mode 100644 include/linux/platform_data/lv5207lp.h
 create mode 100644 include/video/gpio_backlight.h

-- 
Regards,

Laurent Pinchart


^ permalink raw reply

* Re: [RFC v2 0/5] Common Display Framework
From: Tomi Valkeinen @ 2012-11-23 14:51 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: linux-fbdev, dri-devel, linux-media, Archit Taneja,
	Benjamin Gaignard, Bryan Wu, Inki Dae, Jesse Barker,
	Kyungmin Park, Marcus Lorentzon, Maxime Ripard, Philipp Zabel,
	Ragesh Radhakrishnan, Rob Clark, Sascha Hauer, Sebastien Guiriec,
	Sumit Semwal, Thomas Petazzoni, Tom Gall, Vikas Sajjan
In-Reply-To: <1353620736-6517-1-git-send-email-laurent.pinchart@ideasonboard.com>

[-- Attachment #1: Type: text/plain, Size: 3954 bytes --]

Hi,

On 2012-11-22 23:45, Laurent Pinchart wrote:
> From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
> 
> Hi everybody,
> 
> Here's the second RFC of what was previously known as the Generic Panel
> Framework.

Nice work! Thanks for working on this.

I was doing some testing with the code, seeing how to use it in omapdss.
Here are some thoughts:

In your model the DSS gets the panel devices connected to it from
platform data. After the DSS and the panel drivers are loaded, DSS gets
a notification and connects DSS and the panel.

I think it's a bit limited way. First of all, it'll make the DT data a
bit more complex (although this is not a major problem). With your
model, you'll need something like:

soc-base.dtsi:

dss {
	dpi0: dpi {
	};
};

board.dts:

&dpi0 {
	panel = &dpi-panel;
};

/ {
	dpi-panel: dpi-panel {
		...panel data...;
	};
};

Second, it'll prevent hotplug, and even if real hotplug would not be
supported, it'll prevent cases where the connected panel must be found
dynamically (like reading ID from eeprom).

Third, it kinda creates a cyclical dependency: the DSS needs to know
about the panel and calls ops in the panel, and the panel calls ops in
the DSS. I'm not sure if this is an actual problem, but I usually find
it simpler if calls are done only in one direction.


What I suggest is take a simpler approach, something alike to how
regulators or gpios are used, even if slightly more complex than those:
the entity that has a video output (SoC's DSS, external chips) offers
that video output as resource. It doesn't know or care who uses it. The
user of the video output (panel, external chips) will find the video
output (to which it is connected in the HW) by some means, and will use
different operations on that output to operate the device.

This would give us something like the following DT data:

soc-base.dtsi:

dss {
	dpi0: dpi {
	};
};

board.dts:

/ {
	dpi-panel: dpi-panel {
		source = <&dpi0>;
		...panel data...;
	};
};

The panel driver would do something like this in its probe:

int dpi_panel_probe()
{
	// Find the video source, increase ref
	src = get_video_source_from_of("source");

	// Reserve the video source for us. others can still get and
	// observe it, but cannot use it as video data source.
	// I think this should cascade upstream, so that after this call
	// each video entity from the panel to the SoC's CRTC is
	// reserved and locked for this video pipeline.
	reserve_video_source(src);

	// set DPI HW configuration, like DPI data lines. The
	// configuration would come from panel's platform data
	set_dpi_config(src, config);

	// register this panel as a display.
	register_display(this);
}


The DSS's dpi driver would do something like:

int dss_dpi_probe()
{
	// register as a DPI video source
	register_video_source(this);
}

A DSI-2-DPI chip would do something like:

int dsi2dpi_probe()
{
	// get, reserve and config the DSI bus from SoC
	src = get_video_source_from_of("source");
	reserve_video_source(src);
	set_dsi_config(src, config);

	// register as a DPI video source
	register_video_source(this);
}


Here we wouldn't have similar display_entity as you have, but video
sources and displays. Video sources are elements in the video pipeline,
and a video source is used only by the next downstream element. The last
element in the pipeline would not be a video source, but a display,
which would be used by the upper layer.

Video source's ops would deal with things related to the video bus in
question, like configuring data lanes, sending DSI packets, etc. The
display ops would be more high level things, like enable, update, etc.
Actually, I guess you could consider the display to represent and deal
with the whole pipeline, while video source deals with the bus between
two display entities.

 Tomi



[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 899 bytes --]

^ permalink raw reply

* [PATCH] video: vt8505: Use devm_* APIs
From: Tushar Behera @ 2012-11-23 12:09 UTC (permalink / raw)
  To: linux-kernel, linux-fbdev; +Cc: FlorianSchandinat, linux, patches

Use devm_request_and_ioremap(), dmam_alloc_coherent() APIs to cleanup
driver probe and remove functions. This also fixes a possible memory
leak as the memory allocated by dma_alloc_coherent() was not getting
freed up.

Signed-off-by: Tushar Behera <tushar.behera@linaro.org>
---

This patch has only been build tested.

 drivers/video/wm8505fb.c |   46 +++++++++-------------------------------------
 1 files changed, 9 insertions(+), 37 deletions(-)

diff --git a/drivers/video/wm8505fb.c b/drivers/video/wm8505fb.c
index 77539c1..95539af 100644
--- a/drivers/video/wm8505fb.c
+++ b/drivers/video/wm8505fb.c
@@ -281,8 +281,7 @@ static int __devinit wm8505fb_probe(struct platform_device *pdev)
 			sizeof(u32) * 16, GFP_KERNEL);
 	if (!fbi) {
 		dev_err(&pdev->dev, "Failed to initialize framebuffer device\n");
-		ret = -ENOMEM;
-		goto failed;
+		return -ENOMEM;
 	}
 
 	strcpy(fbi->fb.fix.id, DRIVER_NAME);
@@ -310,29 +309,19 @@ static int __devinit wm8505fb_probe(struct platform_device *pdev)
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (res = NULL) {
 		dev_err(&pdev->dev, "no I/O memory resource defined\n");
-		ret = -ENODEV;
-		goto failed_fbi;
+		return -ENODEV;
 	}
 
-	res = request_mem_region(res->start, resource_size(res), DRIVER_NAME);
-	if (res = NULL) {
-		dev_err(&pdev->dev, "failed to request I/O memory\n");
-		ret = -EBUSY;
-		goto failed_fbi;
-	}
-
-	fbi->regbase = ioremap(res->start, resource_size(res));
+	fbi->regbase = devm_request_and_ioremap(&pdev->dev, res);
 	if (fbi->regbase = NULL) {
-		dev_err(&pdev->dev, "failed to map I/O memory\n");
-		ret = -EBUSY;
-		goto failed_free_res;
+		dev_err(&pdev->dev, "failed to request and map I/O memory\n");
+		return -EBUSY;
 	}
 
 	np = of_parse_phandle(pdev->dev.of_node, "default-mode", 0);
 	if (!np) {
 		pr_err("%s: No display description in Device Tree\n", __func__);
-		ret = -EINVAL;
-		goto failed_free_res;
+		return -EINVAL;
 	}
 
 	/*
@@ -351,7 +340,7 @@ static int __devinit wm8505fb_probe(struct platform_device *pdev)
 	ret |= of_property_read_u32(np, "bpp", &bpp);
 	if (ret) {
 		pr_err("%s: Unable to read display properties\n", __func__);
-		goto failed_free_res;
+		return ret;
 	}
 
 	of_mode.vmode = FB_VMODE_NONINTERLACED;
@@ -365,7 +354,7 @@ static int __devinit wm8505fb_probe(struct platform_device *pdev)
 
 	/* try allocating the framebuffer */
 	fb_mem_len = of_mode.xres * of_mode.yres * 2 * (bpp / 8);
-	fb_mem_virt = dma_alloc_coherent(&pdev->dev, fb_mem_len, &fb_mem_phys,
+	fb_mem_virt = dmam_alloc_coherent(&pdev->dev, fb_mem_len, &fb_mem_phys,
 				GFP_KERNEL);
 	if (!fb_mem_virt) {
 		pr_err("%s: Failed to allocate framebuffer\n", __func__);
@@ -383,8 +372,7 @@ static int __devinit wm8505fb_probe(struct platform_device *pdev)
 
 	if (fb_alloc_cmap(&fbi->fb.cmap, 256, 0) < 0) {
 		dev_err(&pdev->dev, "Failed to allocate color map\n");
-		ret = -ENOMEM;
-		goto failed_free_io;
+		return -ENOMEM;
 	}
 
 	wm8505fb_init_hw(&fbi->fb);
@@ -420,21 +408,12 @@ static int __devinit wm8505fb_probe(struct platform_device *pdev)
 failed_free_cmap:
 	if (fbi->fb.cmap.len)
 		fb_dealloc_cmap(&fbi->fb.cmap);
-failed_free_io:
-	iounmap(fbi->regbase);
-failed_free_res:
-	release_mem_region(res->start, resource_size(res));
-failed_fbi:
-	platform_set_drvdata(pdev, NULL);
-	kfree(fbi);
-failed:
 	return ret;
 }
 
 static int __devexit wm8505fb_remove(struct platform_device *pdev)
 {
 	struct wm8505fb_info *fbi = platform_get_drvdata(pdev);
-	struct resource *res;
 
 	device_remove_file(&pdev->dev, &dev_attr_contrast);
 
@@ -445,13 +424,6 @@ static int __devexit wm8505fb_remove(struct platform_device *pdev)
 	if (fbi->fb.cmap.len)
 		fb_dealloc_cmap(&fbi->fb.cmap);
 
-	iounmap(fbi->regbase);
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	release_mem_region(res->start, resource_size(res));
-
-	kfree(fbi);
-
 	return 0;
 }
 
-- 
1.7.4.1


^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox